Android:嵌套底部单击/拖动触摸事件问题

时间:2017-05-02 15:55:15

标签: android android-recyclerview androiddesignsupport bottom-sheet

我有一个底部工作表嵌套在另一个底部工作表中FrameLayouts使用BottomSheet布局行为)

我还有一些附加点击监听器的“窥视视图”(FrameLayouts),在点击时分别展开底部工作表。

因此该应用程序基本上有3个主屏幕。 “主容器”,然后是第一个“底部薄片”,可以全屏展开,然后在第一个底部薄片的底部,是第二个底部薄片,也可以全屏展开。

问题:

当我将RecyclerView添加到嵌套的底部“容器”视图时,拖动停止为第二个窥视视图工作(Sheet 2 Peek)。如果我删除查看视图ClickListener RecyclerView,那么事情似乎完全正常。

期望的结果:

两个底部工作表都应保持可拖动状态,并且应该可以单击窥视视图以展开其父底部工作表。底部工作表应该像通常那样响应嵌套的滚动。

我尝试删除ClickListener并使用触摸手势,但我尝试的任何内容似乎都没有帮助。

我正在使用v25.3.1设计支持库,我能够在运行4.4.4库存的Galaxy S4和运行7.1.2库存的Nexus 6P上重现此问题。 (我没有任何其他设备可用)。

我还在github上为有兴趣仔细研究的人创建了一个测试项目: https://github.com/timusus/bottomsheet-test

以下是一些展示布局的屏幕截图:

1 2 3

布局结构如下所示(为清晰起见,省略了一些代码):

<CoordinatorLayout>

    <FrameLayout
        android:id="@+id/mainContainer" 
        android:layout_height="match_parent"/>

    <FrameLayout
        android:id="@+id/sheet1" 
        android:layout_height="match_parent"
        app:layout_behavior="CustomBottomSheetBehavior"
        app:behavior_peekHeight="64dp">

        <FrameLayout
            android:id="@+id/sheet1Container"
            android:layout_height="match_parent"/>

        <CoordinatorLayout>

        <FrameLayout
            android:id="@+id/sheet2
            android:layout_height="match_parent"
            app:layout_behavior="CustomBottomSheetBehavior"
            app:behavior_peekHeight="64dp">

            <FrameLayout
                android:id="@+id/sheet2Container"
                android:layout_height="match_parent">

                <!-- Problematic RecyclerView -->
                <RecyclerView 
                android:layout_height="match_parent"/>

            </FrameLayout>

            <!-- Problematic Click Listener on this view -->
            <FrameLayout 
                android:id="@+id/sheet2PeekView"
                android:layout_height=64dp"/>

        </FrameLayout>

        </CoordinatorLayout>

        <FrameLayout
            android:id="@+id/sheet1PeekView"
            android:layout_height=64dp"/>

    </FrameLayout>
</CoordinatorLayout/>

CustomBottomSheetBehavior只是BottomSheetBehavior的一个简单子类,可以防止第一张图片在第二张图片展开或拖动时拦截触摸事件。这样可以将第二张纸从“展开”拖动到“折叠”,而不会折叠第一张纸。

public class CustomBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {

    private boolean allowDragging = true;

    public void setAllowDragging(boolean allowDragging) {
        this.allowDragging = allowDragging;
    }

    @Override
    public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
        if (!allowDragging) {
            return false;
        }

        return super.onInterceptTouchEvent(parent, child, event);
    }
}

我不相信BottomSheetBehavior的自定义与此问题相关,但为了完整性,以下是它的使用方法:

FrameLayout sheet1 = (FrameLayout) findViewById(R.id.sheet1);
bottomSheetBehavior1 = (CustomBottomSheetBehavior) BottomSheetBehavior.from(sheet1);

FrameLayout sheet2 = (FrameLayout) findViewById(R.id.sheet2);
       bottomSheetBehavior2 = (CustomBottomSheetBehavior) BottomSheetBehavior.from(sheet2);
       bottomSheetBehavior2.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
           @Override
           public void onStateChanged(@NonNull View bottomSheet, int newState) {
                //If the second sheet is expanded or dragging, don't allow the first sheet to respond to touch events.
               if (newState == BottomSheetBehavior.STATE_EXPANDED || newState == BottomSheetBehavior.STATE_DRAGGING) {
                   bottomSheetBehavior1.setAllowDragging(false);
               } else {
                   bottomSheetBehavior1.setAllowDragging(true);
               }
           }

我似乎无法弄清楚这是否与onInterceptTouchEvent的{​​{1}}有关,内部BottomSheetRecyclerView偷窃触摸的嵌套滚动处理事件,上述事物的组合或其他事物。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:13)

<强>固定

  

我似乎无法弄清楚这是否与此有关   BottomSheet的onInterceptTouchEvent,嵌套滚动处理   内部RecyclerView,View.ClickListener窃取触摸事件,a   以上的组合,或其他一切。

它是以上 CustomBottomSheetBehavior View.ClickListener

的组合

问题 bottomSheetBehavior1 正在拖动 getSheet2PeekView 时执行拖动事件,因此检测 getSheet2PeekView 上的触摸事件并设置 bottomSheetBehavior1 拖动false bottomSheetBehavior2 true

解决方案

输入此代码,您的问题就解决了。

findViewById(getSheet2PeekViewResId()).setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            Log.e(TAG, "onTouch: ");
            bottomSheetBehavior1.setAllowDragging(false);
            bottomSheetBehavior2.setAllowDragging(true);
            return false;
        }
    });

还为您的回购邮件创建了 Pull Request ,并进行了全面的更改。