【问题标题】:OnTouch works, but OnClickListener doesn't?OnTouch 有效,但 OnClickListener 无效?
【发布时间】:2018-11-08 10:18:11
【问题描述】:

我创建了一个可以重复使用的小部件/控件,我通过扩展 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  
        }

    });

这是为什么?

【问题讨论】:

  • 你是否将这两个都添加到同一个对象中?
  • @nicholas.hauschild - 不,一次一个 - 将另一个注释掉..
  • 您必须在 onTouchListener 中返回 True 以防止事件被消耗。
  • @harvey_slash,实际上返回 True 意味着它必须被消耗。所以不消费它,你必须返回 false
  • 我从 ontouchlistener 返回了 false 但它不起作用。

标签: android android-view onclicklistener ontouchlistener


【解决方案1】:

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

你应该这样做:

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

【讨论】:

  • 为我工作。从 onTouch 返回 false 使 onClick 工作。
【解决方案2】:

为了确保您的视图是可点击的,需要检查以下几点:

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

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

【讨论】:

  • 感谢您的回复。我尝试将所有这些设置为 true,但没有成功。
  • 将我的扩展相对布局设置为“this.setClickable(true);”实际上是答案。我使用“Toast”消息作为调试语句而不是 logcat。原来我使用了错误的上下文对象。谢谢兄弟...
【解决方案3】:

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

来自文档:

onTouch() - 这会返回一个布尔值来指示 你的听众是否消费这个 事件。重要的是 这个事件可以有多个动作 彼此跟随。所以,如果你 向下动作时返回 false 收到事件,您表示 您尚未消费该活动并且 也对后续不感兴趣 此事件的操作。因此,你 不会被要求进行任何其他 事件中的动作,例如 手指手势,或最终向上 动作事件。

编辑

question 中找到了解决方案,我自己尝试了一下。

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

【讨论】:

  • 很有趣,很高兴知道...但是,当我测试 onClick 时,我注释掉了 OnTouch
  • 感谢您的更新。但是,我不确定你的意思。在触摸事件中,这会去哪里?我尝试在 OnTouchListener 中替换“return true” - “事件”是“MotionEvent”,超类无法识别它。
【解决方案4】:

要在您的onTouch() 中执行此返回 false,如下所示:

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

【讨论】:

  • 但这会禁用您的 ontouch 监听器...这与将其从您的应用程序中删除是一样的。
【解决方案5】:

您可以通过 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;
        }
    });

【讨论】:

    【解决方案6】:

    如果您出于某种原因重写 onMotionEvent() 方法并且在这种情况下需要返回 true/false,您可以通过在之前重写的 onMotionEvent() 中调用 this.performClick() 来手动触发 OnClickListener() 回调你返回真/假。

    【讨论】:

      【解决方案7】:

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

      【讨论】:

        【解决方案8】:

        如果您尝试返回 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...
        

        【讨论】:

          猜你喜欢
          • 2017-01-08
          • 2012-05-08
          • 2017-03-15
          • 2014-10-30
          • 2011-03-08
          • 2013-11-27
          • 2010-11-29
          • 2017-12-13
          • 2015-01-05
          相关资源
          最近更新 更多