I have decided to work on an Android app that uses very similar technology to that of an app I have seen before. I wanted to string together multiple button presses to equat
Alright so I have given this a go, and I believe this will help you get down the path you are attempting given my current understanding of your requirements. I have been quite verbose in my commenting of the class, what I am doing, and why. I hope it is helpful and doesn't feel like pandering. It sounded maybe you were pretty new to Java and Android and I felt the added explanation might be useful.
I am sure there are edge cases and bugs that have been missed, but should be a good start.
Android Activity Class -- MainActivity.java
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
/**
* TAG is typically used for the Log class if you want to see debug/error information in logcat
*/
public static final String TAG = MainActivity.class.getSimpleName();
/**
* Constant to delay before attempting to resolve button presses to an input
*/
public static final int INPUT_HANDLE_DELAY_MS = 500;
/**
* Buttons have naming convention button
*/
private Button mButton00;
private Button mButton10;
private Button mButton01;
private Button mButton11;
private Button mButton02;
private Button mButton12;
/**
* Where we are going to store the input generated by button presses
*/
private EditText mEditText;
/**
* Where the lookup based on ids is going to happen and convert it to a character
*/
private static Map mLookupMap;
/**
* I am not 100% sure if this is needed, but because we will be attempting to write to the mInputQueue,
* and read from it, i've created a lock
*/
private static final Object mLock = new Object();
/**
* Where we are going to store the input generated by button presses
*/
private Queue mInputQueue= new LinkedList<>();
/**
* Android Handler class to help with the timer, and executing our runnable to handle the
* button resolution
*/
private Handler mHandler = new Handler();
/**
* Runnable to cause the application to check if there is valid input
*/
private Runnable mHandleInputRunnable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.buttons);
// method call to initialize the lookup map
initializeLookup();
// Obtain all the references from the layout that we are going to need to use
mEditText = (EditText) findViewById(R.id.edit_text);
mButton00 = (Button) findViewById(R.id.button_0_0);
mButton10 = (Button) findViewById(R.id.button_1_0);
mButton01 = (Button) findViewById(R.id.button_0_1);
mButton11 = (Button) findViewById(R.id.button_1_1);
mButton02 = (Button) findViewById(R.id.button_0_2);
mButton12 = (Button) findViewById(R.id.button_1_2);
// above, the activity implements the OnClickListener interface, set the activity to handle
// the clicks of all of the buttons
mButton00.setOnClickListener(this);
mButton10.setOnClickListener(this);
mButton01.setOnClickListener(this);
mButton11.setOnClickListener(this);
mButton02.setOnClickListener(this);
mButton12.setOnClickListener(this);
// initialize the Runnable to do what we need it to do when we get a 'tick'
mHandleInputRunnable = new Runnable() {
@Override
public void run() {
handleAlarmTrigger();
}
};
}
@Override
public void onClick(View v) {
if (null != mInputQueue) {
synchronized (mLock) {
mInputQueue.add(v.getId());
}
}
resetHandler();
}
/**
* Helper method to do the initialization of the map. Sorry about the order for the button
* presses. They are a little sporadic, no real rhyme or reason.
*/
private void initializeLookup() {
if (null != mLookupMap) {
return;
}
mLookupMap = new HashMap<>();
/*
1 button characters, use String.valueOf() instead of buildStringFromIds() as there is only
one id
*/
mLookupMap.put(String.valueOf(R.id.button_0_0), "A");
mLookupMap.put(String.valueOf(R.id.button_1_0), "B");
mLookupMap.put(String.valueOf(R.id.button_0_1), "C");
mLookupMap.put(String.valueOf(R.id.button_1_1), "D");
mLookupMap.put(String.valueOf(R.id.button_0_2), "E");
mLookupMap.put(String.valueOf(R.id.button_1_2), "F");
/*
2 button characters
*/
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_1_0), "G");
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_0_1), "H");
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_1_1), "I");
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_0_2), "J");
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_1_2), "K");
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_0_0), "L");
/*
3 button characters
*/
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_1_0, R.id.button_0_1), "M");
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_0_1, R.id.button_0_2), "N");
mLookupMap.put(buildStringFromIds(R.id.button_1_0, R.id.button_1_1, R.id.button_1_2), "O");
mLookupMap.put(buildStringFromIds(R.id.button_1_0, R.id.button_0_1, R.id.button_1_2), "P");
mLookupMap.put(buildStringFromIds(R.id.button_1_2, R.id.button_1_2, R.id.button_0_1), "Q");
mLookupMap.put(buildStringFromIds(R.id.button_1_2, R.id.button_1_2, R.id.button_0_1), "R");
/*
4 button characters
*/
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_0_0, R.id.button_0_0, R.id.button_0_0), "S");
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_1_0, R.id.button_0_1, R.id.button_1_0), "T");
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_0_1, R.id.button_0_2, R.id.button_0_1), "U");
mLookupMap.put(buildStringFromIds(R.id.button_1_0, R.id.button_1_1, R.id.button_1_2, R.id.button_1_1), "V");
mLookupMap.put(buildStringFromIds(R.id.button_1_0, R.id.button_0_1, R.id.button_1_2, R.id.button_0_2), "W");
mLookupMap.put(buildStringFromIds(R.id.button_1_2, R.id.button_1_2, R.id.button_0_1, R.id.button_1_2), "X");
/*
5 button characters
*/
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_0_0, R.id.button_0_0, R.id.button_0_0, R.id.button_0_0), "Y");
mLookupMap.put(buildStringFromIds(R.id.button_0_0, R.id.button_1_0, R.id.button_0_1, R.id.button_1_0, R.id.button_1_1), "Z");
}
/**
* Helper method to poll all of the values out of the queue, and create a key. This may or may
* not be a valid key into the map. It depends on the button presses.
*
* @param queue the input queue where we store the id correlating to the button that was pressed
* @return String representing a key into the map
*/
private String buildStringFromQueue(Queue queue) {
StringBuilder sb = new StringBuilder();
if (null != queue) {
Integer pollValue;
synchronized (mLock) {
while ((pollValue = queue.poll()) != null) {
sb.append(pollValue);
}
}
}
return sb.toString();
}
/**
* Helper method to turn 1 to many R.id.button* into a string for a key as a lookup for a character
* value
*
* The "..." means that the method can accept 1 or more values of the defined type
*
* @param ids 1 or more ids
* @return String representing the ids as key into the map
*/
private String buildStringFromIds(int... ids) {
StringBuilder sb = new StringBuilder();
for (int id : ids) {
sb.append(id);
}
return sb.toString();
}
/**
* Helper method that is called each time there is a button click to either start or re-start
* the time before resolving input
*/
private void resetHandler() {
// null checks for the values we will be operating on
if (null != mHandler && null != mHandleInputRunnable) {
/**
* remove the current runnable the handler may/may not have set, and reset it with the
* delay. This is essentially resetting the time before the app takes the button press
* and tries to do a lookup in the map.
*/
mHandler.removeCallbacks(mHandleInputRunnable);
mHandler.postDelayed(mHandleInputRunnable, INPUT_HANDLE_DELAY_MS);
}
}
/**
* Helper method that is called from the Runnable to attempt to handle the input
*/
private void handleAlarmTrigger() {
// just to be safe, always check the queue for null, and don't handle if empty. Also
// we will be setting values on the EditText, ensure it is non-null as well
if (null != mEditText &&
null != mInputQueue &&
!mInputQueue.isEmpty()) {
// Obtain the key from the input we have stored. This will provide a look up into the
// map
String mapKey = buildStringFromQueue(mInputQueue);
// only try and append this if it was a valid set of button presses, and the map
// actually has a value
if (null != mapKey &&
!mapKey.isEmpty() &&
mLookupMap.containsKey(mapKey)) {
mEditText.append(mLookupMap.get(mapKey));
}
// remove all stored values from the queue so we may restart the button presses
synchronized (mLock) {
mInputQueue.clear();
}
}
}
}
Android Layout -- buttons.xml