【问题标题】:Android: Intercept touch gesture handling from the parent to the child viewAndroid:从父视图到子视图的拦截触摸手势处理
【发布时间】:2017-05-12 06:54:24
【问题描述】:

所以我有以下视图结构:

  • 线性布局
    • 水平滚动视图
    • 其他子视图

父 LinearLayout 是可点击的,有一个自定义选择器(按下时改变颜色)。我希望能够触摸 LinearLayout 中的 Horizo​​ntalScrollView,并且只要不是滚动动作,仍然可以处理 LinearLayout 中的触摸。如果我进行滚动动作,那么 Horizo​​ntalScrollView 应该拦截手势并取消 LinearLayout 的触摸。基本上,我希望能够拦截来自子视图的手势,而不是标准的父视图。

我尝试通过创建执行以下操作的扩展类来手动处理 MotionEvent:

线性布局

public override bool OnInterceptTouchEvent(MotionEvent ev)
{
    // Handle the motion event even if a child returned true for OnTouchEvent
    base.OnTouchEvent(ev);
    return base.OnInterceptTouchEvent(ev);
}

水平滚动视图

public override bool OnTouchEvent(MotionEvent e)
{
    if (e.Action == MotionEventActions.Down)
    {
        _intialXPos = e.GetX();
    }

    if (e.Action == MotionEventActions.Move)
    {
        float xDifference = Math.Abs(e.GetX() - _intialXPos);
        if (xDifference > _touchSlop)
        {
            // Prevent the parent OnInterceptTouchEvent from being called, thus it will no longer be able to handle motion events for this gesture
            Parent.RequestDisallowInterceptTouchEvent(true);
        }
    }

    return base.OnTouchEvent(e);
}

这几乎奏效了。当我触摸 Horizo​​ntalScrollView 时,LinearLayout 显示按下状态 UI,并在单击完成时激活。如果我触摸并滚动 Horizo​​ntalScrollView 然后滚动工作。当我放开滚动时,LinearLayout 的单击处理程序不会触发,因为它被拦截了。但问题是,在我开始滚动之前,LinearLayout 会更改为按下状态,即使在手势完成后它也不会重置。在我尝试手动取消 LinearLayout 手势的额外尝试中,我一直遇到其他问题。此外,LinearyLayout 内部还有其他按钮,单击时不应允许父 LinearLayout 显示按下状态。有什么建议么?是否有拦截孩子触摸事件的固定模式?我敢肯定,如果两个类都相互了解,这是可能的,但我试图避免耦合它们。

【问题讨论】:

    标签: android ontouchlistener motionevent


    【解决方案1】:

    以下适用于所有情况:

    InterceptableLinearLayout

    public override bool DispatchTouchEvent(MotionEvent e)
    {
        bool dispatched = base.DispatchTouchEvent(e);
        // Handle the motion event even if a child returns true in OnTouchEvent
        // The MotionEvent may have been canceled by the child view
        base.OnTouchEvent(e);
    
        return dispatched;
    }
    
    public override bool OnTouchEvent(MotionEvent e)
    {
        // We are calling OnTouchEvent manually, if OnTouchEvent propagates back to this layout do nothing as it was already handled.
        return true;
    }
    

    InterceptCapableChildView

    public override bool OnTouchEvent(MotionEvent e)
    {
        bool handledTouch = base.OnTouchEvent(e);
    
        if ([Meets Condition to Intercept Gesture])
        {
            // If we are inside an interceptable viewgroup, intercept the motionevent by sending the cancel action to the parent
            e.Action = MotionEventActions.Cancel;
        }
    
        return handledTouch;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多