21

我创建了一个可以重用的小部件/控件,我通过扩展RelativeLayout. 然后,在我的一个活动中,我在一个循环中创建了一堆这些小部件。但是,当我想让每个小部件响应点击时,我遇到了一个问题。

我发现设置OnTouchListener有效:

 this.setOnTouchListener(new OnTouchListener(){
        public boolean onTouch(View arg0, MotionEvent arg1) {
           //Triggers debug message
        }       
    });

OnClickListener没有:

  this.setOnClickListener(new View.OnClickListener(){
        public void onClick(View v) {
           //Doesn't trigger debug message  
        }

    });

为什么是这样?

4

8 回答 8

52

您应该确保 TouchListener 没有“消耗”触摸事件。如果您从该onTouch()方法返回 true,Android 将认为它已消耗,并且不会将其传递给其他各种触摸处理程序(我假设将包括 ClickListener)。

你应该做:

this.setOnTouchListener(new OnTouchListener(){
    public boolean onTouch(View arg0, MotionEvent arg1) {
        //Triggers debug message
        return false;
    }       
});
于 2011-03-12T15:37:28.713 回答
17

以下是一些需要检查的事项,以确保您的视图是可点击的:

View.setClickable()
View.setEnabled()
View.setFocusable()
View.setFocusableInTouchMode()

根据您希望获得的确切行为,您需要将其中一项或多项设置为开启。由于您正在获取 onTouch 事件,我的猜测是您需要 setClickable。但我必须查看视图创建代码才能确定。

于 2011-03-12T15:34:00.507 回答
16

您是否正确返回布尔 onTouch 值?

从文档:

onTouch() - 这将返回一个布尔值来指示您的侦听器是否使用此事件。重要的是这个事件可以有多个相互跟随的动作。因此,如果在接收到 down 操作事件时返回 false,则表明您尚未消费该事件,并且对该事件的后续操作也不感兴趣。因此,事件中的任何其他操作都不会调用您,例如手指手势或最终的向上操作事件。

编辑

在这个问题中找到了解决方案,然后自己尝试了一下。

您需要return super.onTouchEvent(event);在 onTouchEvent 代码中使用它。添加后, OnClickListener 开始工作。

于 2011-03-12T15:38:40.500 回答
5

要像这样执行此返回 false onTouch()

this.setOnTouchListener(new OnTouchListener(){    
        public boolean onTouch(View arg0, MotionEvent arg1) {   
            return false;
        }       
});
于 2012-04-26T05:55:23.650 回答
2

您可以通过 onTouchListener 实现 onClickListener:

webView.setOnTouchListener(new View.OnTouchListener() {

        public final static int FINGER_RELEASED = 0;
        public final static int FINGER_TOUCHED = 1;
        public final static int FINGER_DRAGGING = 2;
        public final static int FINGER_UNDEFINED = 3;

        private int fingerState = FINGER_RELEASED;


        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {

            switch (motionEvent.getAction()) {

                case MotionEvent.ACTION_DOWN:
                    if (fingerState == FINGER_RELEASED) fingerState = FINGER_TOUCHED;
                    else fingerState = FINGER_UNDEFINED;
                    break;

                case MotionEvent.ACTION_UP:
                    if(fingerState != FINGER_DRAGGING) {
                        fingerState = FINGER_RELEASED;

                        // Your onClick codes

                    }
                    else if (fingerState == FINGER_DRAGGING) fingerState = FINGER_RELEASED;
                    else fingerState = FINGER_UNDEFINED;
                    break;

                case MotionEvent.ACTION_MOVE:
                    if (fingerState == FINGER_TOUCHED || fingerState == FINGER_DRAGGING) fingerState = FINGER_DRAGGING;
                    else fingerState = FINGER_UNDEFINED;
                    break;

                default:
                    fingerState = FINGER_UNDEFINED;

            }

            return false;
        }
    });
于 2014-02-03T15:03:27.303 回答
1

如果由于某种原因重写 onMotionEvent() 方法并且在这种情况下需要返回 true/false,则可以在返回 true 之前通过在重写的 onMotionEvent() 内调用 this.performClick() 手动触发 OnClickListener() 回调/错误的。

于 2012-03-12T03:59:10.627 回答
1

当您在同一个视图上同时需要 onClick 和 onTouch 事件时,请使用GestureDetector

于 2013-10-09T13:18:37.290 回答
0

如果您尝试返回 false:

this.setOnTouchListener(new OnTouchListener(){
    public boolean onTouch(View arg0, MotionEvent arg1) {
        return false;
    }       
});

它不起作用,如果您使用的是 ScrollView,请尝试此解决方案。在 ScrollView 中添加一个 LinearLayout。在其中将 clickable 设置为 true。从 LinearLayout 调用 setOnClickListener 和 setOnTouchListener。

<ScrollView
android:id="@+id/scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbarStyle="outsideOverlay">

<LinearLayout
    android:id="@+id/linearlayout"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusable="true"
    android:gravity="center_vertical"
    android:orientation="vertical">

    <content... />

</LinearLayout>
</ScrollView>


LinearLayout linearlayout = findViewById(R.id.linearlayout);
linearlayout.setOnClickListener...
linearlayout.setOnTouchListener...
于 2018-11-08T02:18:11.430 回答