Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Single method to implement onTouchListener() for multiple buttons

I am trying to see if there is a way to create a single method to implement a touch listener for multiple buttons, seeing as I have quite a few buttons that do almost exactly the same thing. The only difference in what they do is the message that they would send through my sendMessage() method, and how long the button needs to be held down for the message to be sent. If there is a way to do it, what might that be? And also, why wouldn't something like this work?

//Within onCreate Method...
Button mButton = (Button) findViewbyId(R.id.three_sec_button);
mButton = addTouchTimer(mButton, 3, 3);

Calls -

private Button addTouchTimer(Button button, final int sec, final int messageNum){
        button.setOnTouchListener(new View.OnTouchListener() {
            boolean longEnough = false;
            long realTimeLeft = sec * 1000;
            @Override
            // This will make it so that a message is only sent if the button is held down for 3 seconds
            // Otherwise it won't send. It is sent during the hold down process, releasing it returns a false
            // value and no message is sent.
            public boolean onTouch(View arg0, MotionEvent arg1) {
                Log.d("Button", "Touchy Touchy!");
                if(arg1.getAction() == MotionEvent.ACTION_DOWN){
                    buttonPressTime = new CountDownTimer(realTimeLeft, 1000){
                        @Override
                        public void onTick(long millisUntilDone){
                                realTimeLeft = millisUntilDone;
                        }

                        @Override
                        public void onFinish() {  
                            long timeLeft = realTimeLeft;
                            long currTime = System.currentTimeMillis();
                            long realFinishTime = currTime + timeLeft;
                                while(currTime < realFinishTime){
                                    currTime = System.currentTimeMillis();
                                }
                            longEnough = true;
                            sendEmergencyMessage(longEnough, messageNum);
                        }
                    }.start();
                }
                else if(arg1.getAction() == MotionEvent.ACTION_UP){
                    buttonPressTime.cancel();
                    sendMessage(longEnough, messageNum);
                }
                return longEnough;
            }           
        });

        return button;
    }

It just seems that for efficiency's sake there has to be a better way of doing it than implementing individual listeners for each button. As a note, sendMessage() has a Log call in it that utilizes the boolean value, I want to see what it is set as when it is passed. That is the only reason it is called during the release of the button.

like image 220
zgc7009 Avatar asked Jul 25 '13 16:07

zgc7009


2 Answers

Yes you are right, there is a better way. A single TouchListener that handles everything, determining which button it is via the id.

void intialization(){
     Button m1, m2, m3, m4;
     ... //do initialization stuff
     m1.setId(1);
     m2.setId(2);
     m3.setId(3);
     m4.setId(4);
     MyTouchListener touchListener = new MyTouchListener();
     m1.setOnTouchListener(touchListener);
     m2.setOnTouchListener(touchListener);
     m3.setOnTouchListener(touchListener);
     m4.setOnTouchListener(touchListener);
 }

public class MyTouchListener implements OnTouchListener {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch(v.getId()){
            case 1:
                //do stuff for button 1
                break;
            case 2:
                //do stuff for button 2
                break;
            case 3:
                //do stuff for button 3
                break;
            case 4:
                //do stuff for button 4
                break;
        }
        return true;
    }

}

And that's how you'd do it! A numerical approach for the id's is very helpful in this case. Another approach is to have your activity implement the OnTouchListener in your activity, and then your code would be even simpler.

public class MyActivity extends Activity implements OnTouchListener {

    void initialization(){
        Button m1, m2, m3, m4;
        ... //do initialization stuff
        m1.setId(1);
        m2.setId(2);
        m3.setId(3);
        m4.setId(4);
        m1.setOnTouchListener(this);
        m2.setOnTouchListener(this);
        m3.setOnTouchListener(this);
        m4.setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch(v.getId()){
            case 1:
                //do stuff for button 1
                break;
            case 2:
                //do stuff for button 2
                break;
            case 3:
                //do stuff for button 3
                break;
            case 4:
                //do stuff for button 4
                break;
        }
        return true;
    }

}

Note: This approach also will also work for OnClickListener, OnCheckedChangeListener, or any other listener that you would set on an Android view.

like image 160
anthonycr Avatar answered Oct 13 '22 01:10

anthonycr


With ButterKnife it would be like this. (in my case ImageView as buttons)

@OnTouch({R.id.Button1, R.id.Button2, R.id.Button3})
public boolean buttonsTouched(ImageView button, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            --(Your ACTION on Pressed)--
            return true;
        case MotionEvent.ACTION_UP:
            --(Your ACTION on Release)--
            return true;
    }
    return true;
}
like image 29
Jakub S. Avatar answered Oct 12 '22 23:10

Jakub S.