【问题标题】:Android-Touch event detection for both parent and child views simultaneously同时检测父视图和子视图的 Android-Touch 事件
【发布时间】:2015-06-23 10:59:43
【问题描述】:

以下是我的应用程序的布局:

       LinearLayout
            ----Button
               ----ScrollView
                  ----RelativeLayout
                     ----EditText

我在所有这些上创建了一个透明的线性布局,实现了 OnTouchListener 和内部 OnTouch(),返回 false。因此,所有控件都移到了子项下方。但是在 LinearLayout 上,我无法处理 ACTION_MOVE 动作,因为此布局不消耗 MotionEvent 对象。有什么方法可以检测父视图和子视图中的所有触摸事件?

【问题讨论】:

    标签: android android-layout android-activity touch-event


    【解决方案1】:

    根据我的经验,dispatchTouchEvent() 方法不应该被覆盖,因为它有点难以控制。我的建议是onInterceptTouchEvent() 方法。 Android 不支持覆盖此选项。你可以通过创建自己的 View 来劫持它,这是一个从 RelativeLayout 扩展而来的 sn-p:

    public class InterceptTouchRelativeLayout extends RelativeLayout{
    
    public interface OnInterceptTouchListener{
        boolean onInterceptTouch(MotionEvent ev);
    }
    
    private OnInterceptTouchListener onInterceptTouchListener;
    
    public InterceptTouchRelativeLayout(Context context) {
        super(context);
    }
    
    public InterceptTouchRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    public InterceptTouchRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return onInterceptTouchListener.onInterceptTouch(ev);
    }
    
    public void setOnInterceptTouchListener(OnInterceptTouchListener onInterceptTouchListener) {
        this.onInterceptTouchListener = onInterceptTouchListener;
    }
    

    }

    照常使用,

    myView.setOnInterceptTouchListener(new InterceptTouchRelativeLayout.OnInterceptTouchListener() {
            @Override
            public boolean onInterceptTouch(MotionEvent ev) {
                switch (ev.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        // Parent didn't steal this touch event if return false this case.
                        return false;
    
                    case MotionEvent.ACTION_MOVE:
                        // Parent didn't steal this touch event if return false this case.
                        return false;
    
                    case MotionEvent.ACTION_UP:
                        // Parent didn't steal this touch event if return false this case. However, please notice, it's too late for the parent to steal this touch event at this time, it won't work anymore.
                        return true;
                }
    
                return false;
            }
        });
    

    无论如何,我的建议是更多地研究该视图/视图组控制触摸事件的流程。这是onInterceptTouchEvent() 将如何为您的目的而工作的解释:

    • 在其child所在位置触摸parent时,会调用onInterceptTouchEvent(),如果我们在ACTION_DOWN时返回false,则认为parent尚未窃取此触摸事件,并检查其是否孩子被实施onTouch()。这样,只要孩子不调用requestDisallowInterceptTouchEvent(true),父母仍然可以在onInterceptTouchEvent()处理这个触摸事件,孩子可以在自己的onTouch()事件中处理同样的触摸事件。但是,有时需要考虑处理父母的onTouch()事件,以防没有孩子处理触摸事件,所以父母可以处理。

    【讨论】:

      【解决方案2】:

      您可以通过在布局中覆盖 dispatchTouchEvent 来实现。

      public class MyFrameLayout extends LinearLayout {
          @Override
          public boolean dispatchTouchEvent(MotionEvent e) {
              // do what you need to with the event, and then...
              return super.dispatchTouchEvent(e);
          }
      }
      

      然后使用该布局代替通常的 FrameLayout:

          <com.example.android.MyFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:padding="10dip"
              android:id="@+id/rootview">
      
        ...
      

      如果您需要阻止孩子,您也可以完全跳过超级呼叫 收到事件的意见,但我认为这很少见。

      此答案基于 Romain guyreference 答案。

      【讨论】:

      • 我已经尝试过了,但还是第一次调用 dispatchTouchEvent。之后 MotionEvent 对象被任何子布局使用,并且不再被调用。
      • 是否要同时处理父子事件?
      • 是的..我需要处理两种布局。实际上我想要来自外部活动的所有 ACTION_MOVE ,UP ,DOWN 事件。
      • 我用它作为一个包装器 FrameLayout,它覆盖了内联方法,然后将实际膨胀的视图添加到它。效果很好!
      猜你喜欢
      • 1970-01-01
      • 2019-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多