【问题标题】:onTouchListener warning: onTouch should call View#performClick when a click is detectedonTouchListener 警告:当检测到点击时,onTouch 应该调用 View#performClick
【发布时间】:2014-09-17 02:33:19
【问题描述】:

我创建了一个onTouchListener。不幸的是 onTouch() 方法throws我一个警告:

com/calculator/activitys/Calculator$1#onTouch should call View#performClick when a click is detected

这是什么意思?我还没有找到有关此警告的任何信息。完整代码如下:

LinearLayout llCalculatorContent = (LinearLayout) fragmentView.findViewById(R.id.calculator_content);

llCalculatorContent.setOnTouchListener(new View.OnTouchListener() {
            
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Tools.hideKeyboard(getActivity(), getView());
        getView().clearFocus();
        return false;
    }   
});

【问题讨论】:

  • 您想摆脱警告,只需致电v.performClick()。该实现将播放一点声音(如果您在设备上启用了它)并调用您可能尚未覆盖的 onClickListener
  • 您的回答是正确的。谢谢
  • 您好@TrzyGracje,如果您可以共享以下课程,可以吗:Tools.hideKeyboard(getActivity(), getView()); “工具”类
  • 你好@EmmanuelNjorogeOdongo。我在 6 多年前从事那个项目,但我再也无法访问它了。很抱歉我帮不上忙。

标签: android ontouchlistener


【解决方案1】:
onTouch should call View#performClick when a click is detected

你可以抑制 Lint

@SuppressLint("ClickableViewAccessibility")

您应该在onTouchEvent() 中调用performClick()

@Override
public boolean onTouchEvent(MotionEvent event) {
    //Logic 
    performClick();
    return super.onTouchEvent(event);
}

findViewById(R.id.view1).setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        v.performClick();
        return v.onTouchEvent(event);
    }
});

OnTouch flow

阅读更多here

【讨论】:

  • 您不必覆盖performClick()。请分享您的代码
【解决方案2】:

我通过使用 Kotlin 扩展解决了这个警告

首先创建扩展(例如 ViewExtensions.kt)

fun Button.onTouch(touch: (view: View, motionEvent: MotionEvent) -> Unit) {
    setOnTouchListener { v, event ->
        touch(v,event)
        v.performClick()
        true
    }
}

其次,在你的 Fragment 或 Activity 中创建一个函数

private fun onTouchButton(v: View, event: MotionEvent) {
       /* My Amazing implementation */
}

最后,使用扩展

myButton.onTouch { v, event ->
 onTouchButton(v, event)
}

【讨论】:

    【解决方案3】:

    我不得不忽略它。我有一个 TouchListener 来触发一个动画按钮(在我的情况下改变颜色)。但我也有一个点击监听器来完成按钮工作。所以这导致我的点击监听器再次触发。我在触摸事件(Action_Down,Up等)的切换中尝试了它作为默认情况。

    【讨论】:

      【解决方案4】:

      这是一个超级迟到的答案,但我希望它会对某人有所帮助。不久前我遇到了这个警告,我的方法是,创建一个扩展 View.class 的类,然后在该类中创建一个名为 closeKeyboard(View view){} 的公共方法,这就是它的外观:

      public class MyTouchEvent extends View {
      
          public MyTouchEvent(Context context) {
              super(context);
          }
      
          public void closeKeyboard(View view) {
              view.setOnTouchListener((view1, motionEvent) -> {
                  view1.performClick();
             // this is a library handels the closing of keyboard
                  UIUtil.hideKeyboard((Activity) getContext());
                  return false;
              });
          }
      
          @Override
          public boolean performClick() {
              super.performClick();
              return true;
          }
      }
      

      MainActivity 中,我调用了closeKeyboard(view) 并使用父布局作为参数,如下所示:

      new MyTouchEvent(this).collapseKeyboard(parentLayout);
      

      用来关闭键盘的库

      implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC2'
      

      library source

      【讨论】:

        【解决方案5】:

        我在MultiTouchListener 上遇到了类似的问题,并解决了它实现GestureDetector 并监听SingleTap(这不会消除警告,但在我看来开始触发onClick 事件)

        class TouchListener(context: Context) : MultiTouchListener() {
        
            private var tochedView: View? = null
            private var mGestureDetector = CustomGestureDetector()
            private var gestureDetector: GestureDetector = GestureDetector(context, mGestureDetector)
        
            @SuppressLint("ClickableViewAccessibility")
            override fun onTouch(view: View?, event: MotionEvent?): Boolean {
                val aux = super.onTouch(view, event)
        
                tochedView = view
                gestureDetector.onTouchEvent(event)
        
                return aux
            }
        
            private inner class CustomGestureDetector: GestureDetector.SimpleOnGestureListener() {
        
                override fun onSingleTapUp(e: MotionEvent?): Boolean {
                    // this will be called even when a double tap is
                    tochedView?.performClick()
                    return super.onSingleTapUp(e)
                }
        
                override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
                    // this will only be called after the detector is confident that the
                    // user's first tap is not followed by a second tap leading to a double-tap gesture.
                    tochedView?.performClick()
                    return super.onSingleTapConfirmed(e)
                }
        
            }
        
        }
        

        【讨论】:

          【解决方案6】:

          只需调用 performClick 方法,如下所示:

          @Override
          public boolean onTouch(View v, MotionEvent event) {
              v.performClick();
              Tools.hideKeyboard(getActivity(), getView());
              getView().clearFocus();
              return false;
          }   
          

          【讨论】:

            【解决方案7】:

            如果您没有使用明确覆盖 onPerformClickCustom View ,则仅遵循 Secko 的回答不会删除警告。

            除了他的回答之外,要在 android.widget.ButtonButton 这样的类上做同样的事情,你需要制作一个简单的自定义视图来扩展目标视图。

            示例:

            自定义视图类:

            public class UselessButton extends AppCompatButton {
                public UselessButton(Context context) {
                    super(context);
                }
            
                public UselessButton(Context context, AttributeSet attrs) {
                    super(context, attrs);
                }
            
                public UselessButton(Context context, AttributeSet attrs, int defStyle) {
                    super(context, attrs, defStyle);
                }
            
                @Override
                public boolean performClick() {
                    return super.performClick();
                }
            }
            

            XML

            <stackoverflow.onEarth.UselessButton
                android:id="@+id/left"
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="8dp"
                android:layout_marginBottom="8dp"
                android:background="@drawable/left"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.16"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBaseline_toBaselineOf="@+id/right"
                app:layout_constraintVertical_bias="0.5" />
            

            Java

                left.setOnTouchListener((v, event) -> {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        enLeft = 1;
                        enRight = 0;
                        return true;
                    } else if (event.getAction() == MotionEvent.ACTION_UP) {
                        enLeft = 0;
                        v.performClick();
                        return false;
                    } else {
                        return false;
                    }
                });
            

            当前问题:IDE 解决了警告,但在真正的 Android 设备上实际上看不到执行点击操作。

            EDIT:修复了获取点击事件:使用View.setPressed(boolean)

            down.setOnTouchListener((v, event) -> {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    enFront = 0;
                    enBack = 1;
                    left.setPressed(true);
                    return true;
                } else if (event.getAction() == MotionEvent.ACTION_UP) {
                    enBack = 0;
                    v.performClick();
                    v.setPressed(false);
                    return false;
                } else {
                    return false;
                }
            

            【讨论】:

            • setPressed(false) 是否确保 performClick() 在返回 false 时不会以某种方式覆盖?我有返回 false 的代码,因此 viewpage 不应转到指定的选项卡。但由于调用了 v.performClick(),它仍然会转到选项卡并覆盖它。
            【解决方案8】:

            给你:

            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    //some code....
                    break;
                case MotionEvent.ACTION_UP:
                    v.performClick();
                    break;
                default:
                    break;
                }
                return true;
            }
            

            【讨论】:

            • 不应该只在 event==MotionEvent.Action_UP 或类似的情况下调用它吗?另外,返回“false”不会真正调用原始点击方法,所以您应该实际返回“true”吗?
            • @longilong 好吧,如果您愿意,也可以将其设置为使用 switch-case,但这在逻辑上是相同的......
            • 我也有类似的警告。但是我的情况有点不同,因为我在设置 RecyclerView 时设置了一个匿名 OnTouchListener(调用 myRecyclerView.setOnTouchListener。Android Studio 正在用类似的警告标记整个匿名类,即使我添加 v.performClick 警告仍然存在。
            • 如果我们从这个方法返回false,我们不应该被要求调用performClick,对吧?在这种情况下,我不明白为什么 lint 警告仍然存在
            • 没有修复警告。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-07-23
            • 2011-04-30
            • 2010-10-27
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多