8

我正在尝试查看是否有一种方法可以创建一个方法来实现多个按钮的触摸侦听器,因为我有很多按钮可以做几乎完全相同的事情。他们所做的唯一区别是他们将通过我的 sendMessage() 方法发送的消息,以及需要按住按钮多长时间才能发送消息。如果有办法做到这一点,那可能是什么?而且,为什么这样的东西不起作用?

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

通话 -

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;
    }

似乎为了提高效率,必须有比为每个按钮实现单独的侦听器更好的方法。需要注意的是, sendMessage() 在其中有一个使用布尔值的 Log 调用,我想看看它在传递时的设置。这是在释放按钮期间调用它的唯一原因。

4

9 回答 9

20

是的,你是对的,有更好的方法。一个处理所有事情的 TouchListener,通过 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;
    }

}

这就是你的做法!在这种情况下,id 的数值方法非常有用。另一种方法是让您的活动在您的活动中实现 OnTouchListener,然后您的代码会更简单。

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;
    }

}

注意:此方法也适用于 OnClickListener、OnCheckedChangeListener 或您将在 Android 视图上设置的任何其他侦听器。

于 2013-07-25T17:03:52.577 回答
7

使用 ButterKnife会是这样。(在我的情况下 ImageView 作为按钮)

@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;
}
于 2017-04-06T14:32:34.263 回答
4

是的,有更好的方法来做同样的事情。
1)让你的班级实现OnTouchListener
2)将此侦听器添加到应处理触摸事件的每个按钮。像这样:

button1.setOnTouchListener(this);

3)在这个public boolean onTouch(View arg0, MotionEvent arg1) {});

您可以在被触摸的视图上使用 switch case 的方法。第一个参数 iearg0是触摸事件被分派到的视图。在您的情况下,它将是不同的按钮。像这样的东西:

public boolean onTouch(View arg0, MotionEvent arg1) {
    if (arg1.getAction() == MotionEvent.ACTION_DOWN) {
        switch (arg0.getId()) {
        case R.id.button1: // Id of the button
            // Your code goes here
            break;

        case R.id.button2: // Id of the button
            // Your code goes here
            break;

        default:
            break;
        }
    }
    return true;
}
于 2013-07-25T17:06:30.307 回答
1
OnTouchListener mOnTouchListener = new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // Code goes here
    return true;
    }
};

button1.setOnTouchListener(mOnTouchListener);
button2.setOnTouchListener(mOnTouchListener);
于 2013-07-25T18:09:02.253 回答
1

我合并两个答案,这是我的代码

public class MyActivity extends Activity implements OnTouchListener {
Button mGreen, mRed;

void initialization() {

    ... //do initialization stuff

    mGreen.setOnTouchListener(this);
    mRed.setOnTouchListener(this);
}

@Override
public boolean onTouch(View v, MotionEvent event) {


    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            actionDown();
            break;
        case MotionEvent.ACTION_UP:
            actionUp();
            break;

        case MotionEvent.ACTION_POINTER_DOWN:
            break;

        case MotionEvent.ACTION_POINTER_UP:
            break;

        case MotionEvent.ACTION_MOVE:
            actionMove();
            break;
    }

    return true;
}

public void actionDown() {
    switch (view.getId()) {
        case R.id.button_green:
            //todo
            break;

        case R.id.button_red:
            //todo
            break;
    }
}

public void actionUp() {
    switch (view.getId()) {
        case R.id.button_green:
            //todo
            break;


        case R.id.button_red:
            //todo
            break;
    }
}

public void actionMove() {
    switch (view.getId()) {
        case R.id.button_green:
            // todo
            break;

        case R.id.button_red:
            // todo
            break;
    }

}}

我希望这段代码对某人有所帮助

于 2016-02-02T16:18:28.667 回答
0

你为什么不用黄油刀?

@Nullable @OnClick({R.id.btn1, R.id.btn2,R.id.btn3, R.id.btn4})
public void doStuff(Button button) {}
于 2016-04-11T12:26:13.027 回答
0

就我而言,我需要的类似于上面的答案,但我的目的不同......

无论何时触摸屏幕,我都想隐藏我的键盘,无论是UP还是DOWN

   /**
     * Hide keyboard on touching the screen
     * <a href="https://stackoverflow.com/questions/17864143/single-method-to-implement-ontouchlistener-for-multiple-buttons">how to hide on touch</a>
     */
    @OnTouch(R.id.scroll_sign_up_step2_view)
    public boolean hideKeyBoardOnTouch() {
        hideKeyboard();
        return true;
    }
于 2019-02-11T08:42:55.567 回答
0

在 Kotlin 中,您可以使用 onTouch 变量创建对象类,然后在您想要的任何地方使用它。

在 Listeners.kt 中

object Listeners {
    val onTouch = View.OnTouchListener { v: View, event: MotionEvent ->
        //Do anything with view here and check event type
        return@OnTouchListener false
    }
}

然后在你的活动中


button.setOnTouchListener(Listeners.onTouch)

于 2021-02-19T08:24:20.537 回答
0
@Override
        public boolean onTouch(View view, MotionEvent motionEvent)
        {
            switch (motionEvent.getAction() & MotionEvent.ACTION_MASK)
            {
                case MotionEvent.ACTION_DOWN:
                    shouldClick = true;
                    .
                    .
                    break;
                case MotionEvent.ACTION_UP:
                    if (shouldClick)
                        view.performClick();
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    break;
                case MotionEvent.ACTION_MOVE:
                    //Do your stuff
                    shouldClick = false;
                    break;
            }
            rootLayout.invalidate();
            return true;
        }
于 2018-09-09T19:07:56.723 回答