Android: Tapping one to six buttons continuously [one after another] to string together different results

前端 未结 3 912
-上瘾入骨i
-上瘾入骨i 2020-12-06 23:47

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

3条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-07 00:13

    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

    
    
    
    
    
    
    
        

提交回复
热议问题