【问题标题】:Scrolling is not working with CoordinatorLayout + parallax image + BottomSheetLayout滚动不适用于 CoordinatorLayout + 视差图像 + BottomSheetLayout
【发布时间】:2016-08-24 17:05:16
【问题描述】:

简介

我有一个活动,它使用CoordinatorLayoutAppBarLayoutCollapsingToolbarLayout 实现了具有视差标题图像和滚动内容的通用模式。我的 xml 布局如下所示:

<android.support.design.widget.CoordinatorLayout
    android:fitsSystemWindows="true"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <android.support.design.widget.AppBarLayout
        android:fitsSystemWindows="true"
        android:id="@+id/appbar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:fitsSystemWindows="true"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <TextView
                android:background="@color/colorAccent"
                android:gravity="center"
                android:layout_height="250dp"
                android:layout_width="match_parent"
                android:text="ParallaxImage"
                app:layout_collapseMode="parallax"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_height="?attr/actionBarSize"
                android:layout_width="match_parent"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay"/>

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/content"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/text_margin"
            android:layout_width="wrap_content"
            android:text="@string/large_text"/>
    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

正如您在下面的 gif 动画中所见,一切正常。您可以从内容NestedScrollView 以及Toolbar 或视差View 滚动整个屏幕。

问题

Google 引入了BottomSheetBehavior 类(Android 设计支持库23.2)来帮助开发者实现Bottom sheets。我的带有底页的 xml 布局如下所示:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">
        <!-- ommited -->
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <!-- ommited -->
    </android.support.v4.widget.NestedScrollView>

    <LinearLayout
        android:id="@+id/bottomSheet"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:background="@android:color/holo_blue_bright"
        android:orientation="vertical"
        app:behavior_peekHeight="?attr/actionBarSize"
        app:layout_behavior="android.support.design.widget.BottomSheetBehavior">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:gravity="center_vertical"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:text="BottomSheetLayout"
            android:textColor="@android:color/white"/>

        <android.support.v4.widget.NestedScrollView
            android:id="@+id/bottomSheetContent"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scrollbars="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="400dp"
                android:background="@android:color/holo_green_dark"
                android:padding="16dp"
                android:text="@string/large_text"
                android:textColor="@android:color/white"/>

        </android.support.v4.widget.NestedScrollView>
    </LinearLayout>

</android.support.design.widget.CoordinatorLayout>

结果如下所示:

如您所见,现在我无法滚动,如果我从视差View 开始滚动。从内容NestedScrollViewToolbar 滚动按预期工作。

问题

如何管理滚动以从视差View 工作(与第一个 gif 动画中的方式相同)?似乎BottomSheetBehavior 拦截了触摸事件并阻止AppBarLayout (AppBarLayoutBehavior) 处理滚动。但奇怪的是,从Toolbar 滚动有效,视差ViewToolbar 都是AppBarLayout 的子代。

【问题讨论】:

标签: android android-coordinatorlayout android-collapsingtoolbarlayout android-appbarlayout bottom-sheet


【解决方案1】:

我想出了自己的答案:

  • app:layout_behavior="...AppBarLayoutCustomBehavior" 添加到您的appBarLayout

  • 创建该类并从AppBarLayout.Behavior扩展

  • 覆盖onStartNestedScrollonNestedFling

  • 创建一个类似scrollDenial的标志,并将其添加到下面的两个方法中,然后调用super (scrollDenial && super.onStartNestedScroll...)

  • 现在,您需要在每个 onStartNestedScroll 上更新您的拒绝条件。我做了这样的事情:

    https://gist.github.com/recoverrelax/8dd37b54910d70b5cd6a130a070c51e9

附言。抱歉,这是 Kotlin :p 应该不难理解。它解决了bottomSheet问题。

【讨论】:

    【解决方案2】:

    可以通过将 NestedScrollView(或在我的情况下包含 NestedScrollView 的片段)在 FrameLayout 中的 CoordinatorLayout 之外移动并在 NestedScrollView 所在的位置放置一个虚拟视图来解决该问题,如下所示:

    <FrameLayout>
        <CoordinatorLayout>
            <AppBarLayout>
                ...
            </AppBarLayout>
            <View
                android:id="@+id/bottomSheet"
                app:layout_behavior="android.support.design.widget.BottomSheetBehavior" />
        </CoordinatorLayout>
        <NestedScrollView
            android:id="@+id/bottomSheetContent">
            ...
        </NestedScrollView>
    </FrameLayout>
    

    最后,将BottomSheetCallback 添加到滑动时转换实际内容视图的虚拟视图:

    @Override
    public void onSlide(@NonNull View bottomSheet, float slideOffset) {
        bottomSheetContent.setTranslationY((1f - slideOffset) * bottomSheetContent.getHeight());
    }
    

    显然,这是防止 CoordinatorLayout 对任何触摸事件做出反应(并拦截)的唯一方法。 #JustGoogleThings

    【讨论】:

      【解决方案3】:

      我正在复制粘贴我正在使用的 XML。顺便说一句,它在三星 Galaxy S3、华为 Mate 8 和 Moto 上运行,我还没有在模拟器上尝试过(我删除了所有业务内容,只是放置了虚拟小部件)。

      <?xml version="1.0" encoding="utf-8"?>
      <android.support.design.widget.CoordinatorLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      android:id="@+id/coordinatorlayout"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:fitsSystemWindows="true">
      
      <android.support.design.widget.AppBarLayout
          android:id="@+id/appbarlayout"
          android:layout_width="match_parent"
          android:layout_height="256dp"
          android:theme="@style/AppTheme.AppBarOverlay"
          android:fitsSystemWindows="true">
      
          <android.support.design.widget.CollapsingToolbarLayout
              android:id="@+id/collapsing_toolbar"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              app:layout_scrollFlags="scroll|exitUntilCollapsed"
              android:fitsSystemWindows="true"
              app:contentScrim="?attr/colorPrimary"
              app:expandedTitleMarginStart="48dp"
              app:expandedTitleMarginEnd="64dp">
      
              <ImageView
                  android:id="@+id/backdrop"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:scaleType="centerCrop"
                  android:fitsSystemWindows="true"
                  app:layout_collapseMode="parallax"/>
      
      
              <android.support.v7.widget.Toolbar
                  android:id="@+id/toolbar"
                  android:layout_width="match_parent"
                  android:layout_height="?attr/actionBarSize"
                  app:popupTheme="@style/AppTheme.PopupOverlay"
                  app:layout_collapseMode="pin"/>
      
          </android.support.design.widget.CollapsingToolbarLayout>
      </android.support.design.widget.AppBarLayout>
      
      
      
      <android.support.v4.widget.NestedScrollView
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          app:layout_behavior="@string/appbar_scrolling_view_behavior">
      
          <LinearLayout
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              android:paddingBottom="16dp">
      
              <android.support.v7.widget.CardView
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_margin="16dp">
      
                  <LinearLayout
                      style="@style/Widget.CardContent"
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content">
      
                      <TextView
                          android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          android:text="Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo." />
      
                  </LinearLayout>
      
              </android.support.v7.widget.CardView>
      
              <android.support.v7.widget.CardView
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_marginBottom="16dp"
                  android:layout_marginLeft="16dp"
                  android:layout_marginRight="16dp">
      
                  <LinearLayout
                      style="@style/Widget.CardContent"
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content">
      
                      <TextView
                          android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          android:text="TITLE"
                      android:textAppearance="@style/TextAppearance.AppCompat.Title" />
      
                          <TextView
                              android:layout_width="match_parent"
                              android:layout_height="wrap_content"
                              android:text="text 1" />
      
                          <TextView
                              android:layout_width="match_parent"
                              android:layout_height="wrap_content"
                              android:text="text 2" />
      
                          <TextView
                              android:layout_width="match_parent"
                              android:layout_height="wrap_content"
                              android:text="text 3" />
      
                          <TextView
                              android:layout_width="match_parent"
                              android:layout_height="wrap_content"
                              android:text="text 4" />
      
                          <TextView
                              android:layout_width="match_parent"
                              android:layout_height="wrap_content"
                              android:text="text 5" />
      
                      </LinearLayout>
      
                  </android.support.v7.widget.CardView>
              </LinearLayout>
          </android.support.v4.widget.NestedScrollView>
      
      
      <android.support.v4.widget.NestedScrollView
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical"
          app:behavior_peekHeight="100dp"
          android:fitsSystemWindows="true"
          app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
      
          <LinearLayout
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              android:paddingBottom="16dp"
              android:background="@android:color/white"
              android:padding="15dp">
      
              <TextView
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="BOOTOMSHEET TITLE"
                  android:textAppearance="@style/TextAppearance.AppCompat.Title" />
      
              <Button
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="Button1"/>
      
              <TextView
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="text 2"
                  android:layout_margin="10dp"/>
      
              <TextView
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="text 3"
                  android:layout_margin="10dp"/>
      
              <TextView
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="text 4"
                  android:layout_margin="10dp"/>
      
      
              <FrameLayout
                  android:layout_width="match_parent"
                  android:layout_height="320dp"
                  android:background="@color/colorAccent">
      
                  <TextView
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:layout_gravity="center"
                      android:text="Your remaining content here"
                      android:textColor="@android:color/white" />
      
              </FrameLayout>
          </LinearLayout>
      </android.support.v4.widget.NestedScrollView>
      

      【讨论】:

      • 如果你想要一个显示它工作的 gif,告诉我你是怎么做的,我会用它更新答案:)
      • 你能分享更多关于你在代码中得到什么的信息吗?或 gif,你正在尝试的设备,因为就像我说的,我在很多模拟器和真实设备上测试了它并且它运行良好。
      【解决方案4】:

      试试这个

       <LinearLayout
              android:id="@+id/bottomSheet"
              android:layout_width="match_parent"
              android:layout_height="400dp">
      

      将高度 400dp 更改为 wrap_content

      希望对你有用

      【讨论】:

        【解决方案5】:

        这似乎是BottomSheetBehavior 代码中的错误,因为如果您尝试调试CoordinatorLayout 的代码,您会看到当您触摸视差View 时,它将被确定为带有BottomSheetBehavior 的布局而不是HeaderBehavior

        所以我发现的快速解决方法是设置 OnTouchListener 始终返回 true 到您的视差视图:

        View parallaxView = findViewById(R.id.parallax_view);
        parallaxView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });
        

        当然,不要忘记将android:id="@+id/parallax_view" 设置为具有视差折叠模式的视图。

        希望对你有帮助!

        【讨论】:

          【解决方案6】:

          我认为你应该使用NestedScrollViewBottomSheetBehavior,替换blow 作为bootemSheet!

          <android.support.v4.widget.NestedScrollView
              android:id="@+id/bottomSheet"
              android:layout_width="match_parent"
              android:layout_height="400dp"
              android:background="@android:color/holo_blue_bright"
              android:orientation="vertical"
              app:behavior_peekHeight="?attr/actionBarSize"
              app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
          
              <LinearLayout
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:orientation="vertical">
          
                  <TextView
                      android:layout_width="match_parent"
                      android:layout_height="?attr/actionBarSize"
                      android:gravity="center_vertical"
                      android:paddingLeft="16dp"
                      android:paddingRight="16dp"
                      android:text="BottomSheetLayout"
                      android:textColor="@android:color/white"/>
          
                  <ScrollView
                      android:layout_width="match_parent"
                      android:layout_height="match_parent">
          
                      <TextView
                          android:layout_width="match_parent"
                          android:layout_height="400dp"
                          android:background="@android:color/holo_green_dark"
                          android:padding="16dp"
                          android:text="@string/large_text"
                          android:textColor="@android:color/white"/>
                  </ScrollView>
              </LinearLayout>
          
          </android.support.v4.widget.NestedScrollView>
          

          NestedScrollView可以知道如何与工具栏嵌套,而不是LinearLayout

          希望提供帮助!

          【讨论】:

          • 这无关紧要,对我没有帮助...但是谢谢。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多