【问题标题】:Disable DrawerLayout's scrim touch gesture禁用 DrawerLayout 的 scrim 触摸手势
【发布时间】:2015-10-21 11:23:46
【问题描述】:

我需要禁用稀松布上的触摸手势(红色突出显示的部分)。我只想通过滑动来关闭抽屉。

问题是,当抽屉布局打开并且我需要从红色突出显示部分下方的 ListView 中选择一个元素时,发生的情况是抽屉关闭了,只有此时我才能从 ListView 中选择一个元素.

我需要直接从 ListView 中选择元素,打开 Drawer 时也是如此

【问题讨论】:

  • 红色面板只是为了突出显示我需要以自定义方式管理 Drawer 的点击部分的 UI。我用 Photoshop 画出来的
  • 我明天试试你的代码,谢谢你的帮助

标签: android touch gesture drawerlayout


【解决方案1】:

我在这里问了一个已回答的问题:
How to vary between child and parent view group touch events

parent (drawer) ontouchevent 被解雇,而不是 childlistview

我在这里也回答了类似的问题:

https://stackoverflow.com/a/28180281/3956566

您需要管理您的触摸事件,以便由孩子处理。您需要使用 onInterceptTouchEvent 并返回 false。

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    // returning false means the child will handle the touch event.
    return false;
}

然后您管理您touchevent 的列表视图:

@Override
public boolean onTouchEvent(MotionEvent ev) {
    // This method will only be called if the touch event was intercepted in 
    // onInterceptTouchEvent
    // TODO Select your listview item.

}

您还可以确定正在发生什么类型的触摸事件,例如滚动,并确定是子级还是父级来管理事件。

Managing Touch Events in a ViewGroup

我在Understanding Android Input Touch Events System Framework (dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent, OnTouchListener.onTouch)添加了这句话:

根视图开始将事件分派给它的子视图。让我们 假设我们有这个层次结构:

A – ViewGroup1(B 的父级)。
B – ViewGroup2(C 的父级)。
C – 视图(B 的子级)
– 接收触摸/点击/点击。现在根视图将调用 A.dispatchTouchEvent()。现在 ViewGroup.dispatchEvent() 的工作 (not View.dispatchEvent()) 是找出所有的子视图和视图 边界包含触摸点坐标的组(使用命中 测试算法)。当它计算出相关孩子的名单时, 它开始通过调用他们的事件向他们发送事件 dispatchTouchEvent().

这是一个重要的部分。在 dispatchTouchEvent() 之前 调用孩子, A.dispatchTouchEvent() 将首先调用 A.onInterceptTouchEvent() 查看视图组是否有兴趣 拦截事件并自行处理后续手势 (滚动是一个很好的用例,其中 B 上的一扔应该导致 在 A) 上滚动。方法 onInterceptTouchEvent() 仅可用 在视图组(因为他们是可以成为父母/容器的人) 拦截触摸事件的要求)可以保持一个 关注事件并通过返回 true 来劫持它。如果返回 false 然后调度照常继续,即 B.dispatchTouchEvent() (孩子)将被调用。但在返回 true 时,会发生以下情况:

ACTION_CANCEL 将发送给所有孩子。
所有的 随后的手势事件(直到 ACTION_UP/ACTION_CANCEL)将 由事件侦听器 (OnTouchListener.onTouch()) 使用,如果 已定义,否则为 A 级别的事件处理程序 A.onTouchEvent()。
A.onInterceptTouchEvent() 本身将永远不会被再次调用。

With this diagram:

如果您需要更多解释,请告诉我。

【讨论】:

    【解决方案2】:

    你必须像这样创建自定义抽屉

    public class CustomDrawer extends DrawerLayout {
    
    
    
        public CustomDrawer(Context context) {
            super(context);
    
        }
    
        public CustomDrawer(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
        }
    
        public CustomDrawer(Context context, AttributeSet attrs) {
            super(context, attrs);
    
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {
            if(isDrawerOpen(Gravity.START)){
                if(event.getX() > getChildAt(1).getWidth()){
                    return false;
                }
            }
            return super.onInterceptTouchEvent(event);
        }
    
    }
    

    注意:getChildAt(1) 应该是您将重力作为“开始”的孩子,其宽度决定了打开抽屉的宽度。

    希望这能解决你的问题

    【讨论】:

      【解决方案3】:

      只需将android:clickable="true" 添加到抽屉菜单。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-06
        • 2018-03-31
        • 1970-01-01
        • 2014-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-29
        相关资源
        最近更新 更多