【问题标题】:Android: How to prevent any touch events from being passed from a view to the one underneath it?Android:如何防止任何触摸事件从视图传递到其下方?
【发布时间】:2011-12-08 15:30:06
【问题描述】:

具体使用下面的代码,有没有办法修改,让这个新创建的view下的activity不接收任何手势?

View v1 = new View(this);    
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
 1000,
 50,
 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
 PixelFormat.OPAQUE);

params.gravity = Gravity.BOTTOM;
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
wm.addView(v1, params);

【问题讨论】:

    标签: android


    【解决方案1】:

    onTouchEvent 方法添加到顶部位置的视图,然后返回true。 True 将告诉事件冒泡该事件已被消耗,因此防止事件冒泡到其他视图。

    protected boolean onTouchEvent (MotionEvent me) {
        return true;
    }
    

    对于v1,您需要进行导入:

    import android.view.View.OnTouchListener;
    

    然后设置onTouchListener:

    v1.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return true;
        }
    });
    

    【讨论】:

    • 很好的解决方案,非常适合这个问题。不过可能会注意到,它不会阻止底层视图接收来自物理键盘的输入(这意味着如果用户像我一样使用带有物理光标键的手机,他们仍然可以摆弄伪禁用组件)。
    【解决方案2】:

    来自代码

    View v1 = new View(this);   
    v1.setClickable(true);
    v1.setFocusable(true);
    

    来自 xml

    <View
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="My button"
        android:focusable="true"
        android:clickable="true"/>
    

    这将防止触摸和点击事件传播到位于您的视图下方的视图。
    或者,如果您膨胀视图,则在 .xml 中添加 android:clickable="true"

    【讨论】:

    • 请注意,这可能会对单击的触摸动画传递给视图的第一个可聚焦元素产生不利影响。在我的例子中,我有一个 SeekBar 作为可点击视图的子视图,按下它里面的任何地方都会导致 SeekBar 的波纹动画开始。
    • 我认为这是最好的解决方案,因为它可以直接从 xml 完成
    • 这行得通。无需在 Kotlin/Java 中创建 onTouchListener
    【解决方案3】:

    你也可以这样做。您可以将触摸侦听器设置为子视图,然后在onTouch() 事件中,您可以阻止父视图的intercept touch event

    View v = findViewById(R.id.sample_view);
    v.setOnTouchListener(new OnTouchListener() {
        // Setting on Touch Listener for handling the touch inside ScrollView
        @Override
        public boolean onTouch(View v, MotionEvent event) {
        // Disallow the touch request for parent scroll on touch of child view
        v.getParent().requestDisallowInterceptTouchEvent(true);
        return false;
        }
    });
    

    【讨论】:

    • 谢谢...为我工作:-)
    • 你救了我 10+ 天
    • 这有助于我将 recyclerview 嵌套在另一个具有相同滚动方向的 recyclerview 中,并且快速滚动器无法工作。在快速滚动条 onTouch 事件中调用 prent.requestDisallowInterceptTouchEvent(true) 解决了这个问题。
    【解决方案4】:

    您添加如下视图,但请确保它是您添加到 xml 的最后一个视图。 xml 中的最后一项是位于其下所有其他视图之上的项。

    <View
            android:id="@+id/blocking_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#AA666666"
            android:clickable="true"
            android:focusable="true"
            android:visibility="visible"/>
    

    【讨论】:

    • clickable 是这里的重要部分。但是:即使您在其他所有内容之上的布局(也可以是included)设置为match_parent,它也不会覆盖工具栏,这意味着工具栏上的按钮仍然可以点击.
    • 这是一个可行的解决方案,主要是为此拦截器设置最高 ELEVATION。
    【解决方案5】:

    你需要做的只是打电话

    arg0.getParent().requestDisallowInterceptTouchEvent(true);
    

    在 onTouch 函数的开头。喜欢这个 -

        @Override
        public boolean onTouch(View arg0, MotionEvent arg1) {
            arg0.getParent().requestDisallowInterceptTouchEvent(true);
            switch(arg1.getActio){
            }
    
            return false; 
    
         }
    

    【讨论】:

      【解决方案6】:

      我认为最好的方法是添加一个触摸事件并设置返回值True

      如您所见:

        someView.setOnTouchListener(object: View.OnTouchListener {
              override fun onTouch(v: View?, event: MotionEvent?): Boolean{
                  return true
              }
      
          })
      

      返回True表示顶视图正在处理触摸,无需将触摸事件交给其他相关视图。

      【讨论】:

        【解决方案7】:

        我参加聚会有点晚了,但我认为公认的解决方案不是很好。这是一个静态方法,它接受任意数量的视图并禁用此事件冒泡。对于 API 17+(较低的未经测试),这对我来说 100% 的时间都有效

        public static void disableEventBubbling(View... views){
            for(View view : views){
                if(view != null){
                    view.setOnTouchListener(new View.OnTouchListener(){
                       @Override
                        public boolean onTouch(View view, MotionEvent event){
                            view.getParent().requestDisallowInterceptTouchEvent(true);
                            return false;
                        }
                    });
                }
            }
        }
        

        你可以为你想要的任何类型的事件添加一个案例,或者你可以去掉开关,让默认案例成为触摸监听器中的唯一行。

        【讨论】:

          【解决方案8】:

          只需向顶视图背景添加一个点击代理,这将停止下面的视图接收触摸

          linear_layout_background.Click += delegate
                      {
                          // Ensures views underneath does not receive touch events
                      };
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-10-18
            • 2011-12-28
            • 1970-01-01
            • 2017-04-28
            • 2014-05-21
            相关资源
            最近更新 更多