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

Tim*_*eed 9 android android-recyclerview androiddesignsupport bottom-sheet

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

我还有几个'peek views'(FrameLayouts)附加了点击监听器,在点击时分别展开底部工作表.

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

问题:

当我RecyclerView向嵌套的底部工作表'容器'视图添加a时,拖动停止工作以进行第二个peek视图(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/>
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我不相信定制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);
               }
           }
Run Code Online (Sandbox Code Playgroud)

我似乎无法弄清楚,如果这与做onInterceptTouchEventBottomSheet内部的,嵌套的滚动操作RecyclerView,View.ClickListener窃取触摸事件,上述的组合,或别的东西完全.

任何帮助将非常感激.

N J*_*N J 14

固定

我似乎无法弄清楚这是否与BottomSheet的onInterceptTouchEvent,内部RecyclerView的嵌套滚动处理,View.ClickListener窃取触摸事件,上述组合或其他完全相同.

它是上面的CustomBottomSheetBehaviorView.ClickListener的组合

问题是 bottomSheetBehavior1在拖动getSheet2PeekView捕获拖动事件,因此检测getSheet2PeekView上的触摸事件并设置bottomSheetBehavior1拖动falsebottomSheetBehavior2 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;
        }
    });
Run Code Online (Sandbox Code Playgroud)

还通过完全正常的更改为您的仓库创建了Pull Request.

  • 这么简单,我想哭.非常感谢. (2认同)