【问题标题】:Need to disable expand on CollapsingToolbarLayout for certain fragments需要为某些片段禁用 CollapsingToolbarLayout 上的展开
【发布时间】:2015-08-27 01:12:15
【问题描述】:

我有一个控制替换许多片段的 AppCompatActivity。这是我的布局。

activity_main.xml

<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:fitsSystemWindows="true">

<include layout="@layout/activity_main_frame"/>

<android.support.design.widget.NavigationView
    android:id="@+id/navigation_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    android:background="@color/white"
    app:headerLayout="@layout/drawer_header"
    app:menu="@menu/drawer"/>

</android.support.v4.widget.DrawerLayout>

activity_main_frame.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:id="@+id/main_content"
    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:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        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="256dp"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax" />

            <include layout="@layout/activity_main_items"/>

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

            <android.support.design.widget.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:visibility="gone"
                android:layout_gravity="bottom"/>

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

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

    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" >
    </FrameLayout>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab1"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|right|end"
        app:borderWidth="0dp"
        android:src="@drawable/app_ic_slide_wallpaper_dark"
        android:layout_margin="@dimen/big_padding"
        android:clickable="true"/>

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

我的主页片段最初是设置的,这就是我希望折叠工具栏展开的地方,并且工作正常。但是,当我从侧抽屉更改片段时,我想禁用扩展工具栏。

我已经知道如何在选择抽屉项目时折叠它,但我还需要确保它不会展开,除非显示主页片段。这可能吗?

public void collapseToolbar(){
        CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbar.getLayoutParams();
        behavior = (AppBarLayout.Behavior) params.getBehavior();
        if(behavior!=null) {
            behavior.onNestedFling(coordinator, appbar, null, 0, 10000, true);
        }
    }

【问题讨论】:

  • 你有没有找到办法做到这一点?我遇到了同样的问题。
  • 不。我不得不放弃这个概念并将其删除。我认为折叠工具栏不应该与片段一起使用
  • 也许这会有所帮助:stackoverflow.com/a/53433716/878126?

标签: android android-support-library android-toolbar coordinator-layout


【解决方案1】:

禁用滚动片段内容的嵌套滚动:

recyclerView.setNestedScrollingEnabled(false);

如果您正在使用支持库,请使用它:

ViewCompat.setNestedScrollingEnabled(recyclerView, false);

【讨论】:

  • 实际上,此答案中的 recyclerView 应替换为在 xml 中设置了 layout_behavior 属性的任何视图(或 CoordinatorLayout 中的所有此类视图)。它之所以有效,是因为(至少在支持库的 23.0.1 版本中)CoordinatorLayout 的 onStartNestedScroll 方法迭代其子项并询问他们是否接受嵌套滚动。如果没有人接受它,那么它就不会发挥它的滚动魔法。所以,对,自定义 CoordinatorLayout 可能不需要,只有辅助方法就足够了(如果有几个具有 layout_behavior 的孩子)。
  • 此外,在定位棒棒糖之前的设备时应使用ViewCompat.setNestedScrollingEnabled(recyclerView, expanded); 表单。
  • 这不是一个完整的解决方案,因为您仍然可以触摸并拖动 CollapsingToolbarLayout 来扩展它,它只会禁用带有 layout_behavior 的 NestedScrollView 的扩展
  • 太棒了!对我来说很好..谢谢!
  • 效果很好,谢谢。 @nikolay_turpitko 不适用于具有 layout_behavior 属性的视图,仅适用于 RecyclerView。
【解决方案2】:

这个类可以让你禁用/重新启用扩展行为。

public class DisableableAppBarLayoutBehavior extends AppBarLayout.Behavior {
    private boolean mEnabled;

    public DisableableAppBarLayoutBehavior() {
        super();
    }

    public DisableableAppBarLayoutBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setEnabled(boolean enabled) {
        mEnabled = enabled;
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
        return mEnabled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes);
    }

    public boolean isEnabled() {
        return mEnabled;
    }
}

像这样在你的布局中使用它:

<android.support.design.widget.AppBarLayout
    ... other attributes ...
    app:layout_behavior="com.yourpackage.DisableableAppBarLayoutBehavior"
    >
    <!-- your app bar contents -->
</android.support.design.widget.AppBarLayout>

然后,当您要禁用该行为时:

AppBarLayout myAppBar = ....;
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) myAppBar.getLayoutParams();
((DisableableAppBarLayoutBehavior) layoutParams.getBehavior()).setEnabled(false);

【讨论】:

  • 我收到 java.lang.NullPointerException。帮帮我
  • 干得好。但是,它和上面的其他方法有同样的问题:您仍然可以通过直接触摸和拖动 AppBar 本身来扩展内容。
  • 这很好用,除了一个问题,我发现当布局锁定在展开模式时,我无法到达列表的末尾。有没有其他人遇到过这种情况?
  • 为我工作,如果需要,请不要忘记将其默认为 true。
  • 私有布尔 mEnabled = true;
【解决方案3】:

现在,在 v23 的支持库中,您可以轻松控制应用栏的可见性。

只需获取对您的 AppBarLayout 的引用并根据您要加载的片段隐藏/显示它:

private AppBarLayout appBarLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
[...]
appBarLayout = (AppBarLayout) findViewById(R.id.appbar);
[...]
}

public void switchToFragment(Fragment fragment, String tag, boolean expandToolbar){
        FragmentManager fragmentManager = getSupportFragmentManager();

        Fragment currentFragment = fragmentManager.findFragmentByTag(currentFragmentTag);

        if(currentFragment == null || !TextUtils.equals(tag, currentFragmentTag) ){
            currentFragmentTag = tag;
            fragmentManager
                    .beginTransaction()
                    .replace(R.id.flContent, fragment, currentFragmentTag)
                    .commit();

            if(expandToolbar){
                appBarLayout.setExpanded(true,true);
            }else{
                appBarLayout.setExpanded(false,true);
            }
        }
    }

附:不要忘记在 build.gradle 中添加所需的依赖项:

dependencies {  
    compile 'com.android.support:design:23.2.1'
    compile 'com.android.support:appcompat-v7:23.2.1'
    compile 'com.android.support:recyclerview-v7:23.2.1' 
}

编辑: 如果您还想将工具栏锁定在某些片段中(除了折叠),您必须求助于解决方法,因为 CollapsingToolbarLayout 直到现在(支持设计的 v23.2.1)才提供此功能。 Here 你可以找到我建议的解决方法。

【讨论】:

  • setExpanded 也隐藏了我的工具栏。有人知道如何将其设置为折叠但不在屏幕顶部后面吗?
  • 经过数小时的失败尝试,setExpanded() 为我工作!谢谢!
  • 不确定为什么它被接受为答案。当然,这会扩展/折叠您的 AppBarLayout,但是如果您想禁用它,就像问题所说的那样,那么@tachyonflux 的方法就是要走的路。
  • @Ghedeon 过去曾指出这一点。我的 EDIT 是对您对该问题的具体解释的答案。然而,这个问题的标题和解释的措辞可能会被误解,一些未来的观众/谷歌用户实际上希望得到折叠工具栏问题的答案。因此,对此答案的支持和接受标记。
【解决方案4】:

您所要做的就是将 CoordinatorLayout 替换为 CoordinatorLayout 的自定义实现,这将欺骗嵌套滚动已被处理。

MyCoordinatorLayout 实现:

public class MyCoordinatorLayout extends CoordinatorLayout {

    private boolean allowForScroll = false;

    public MyCoordinatorLayout(Context context) {
        super(context);
    }

    public MyCoordinatorLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
        return allowForScroll && super.onStartNestedScroll(child, target, nestedScrollAxes);
    }

    public boolean isAllowForScroll() {
        return allowForScroll;
    }

    public void setAllowForScroll(boolean allowForScroll) {
        this.allowForScroll = allowForScroll;
    }
}

活动视图 xml:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawerLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >

        <!--CONTENT-->

        <com.example.views.MyCoordinatorLayout
            android:id="@+id/coordinator"
            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"
            >

        <com.example.views.ControllableAppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="192dp"
            android:fitsSystemWindows="true"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <android.support.design.widget.CollapsingToolbarLayout
                android:id="@+id/collapsing_toolbar"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                app:contentScrim="?attr/colorPrimary"
                app:expandedTitleMarginBottom="32dp"
                app:expandedTitleMarginEnd="64dp"
                app:expandedTitleMarginStart="48dp"
                app:layout_scrollFlags="scroll|exitUntilCollapsed">

                <ImageView
                    android:id="@+id/header"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="@color/primary"
                    android:fitsSystemWindows="true"
                    android:scaleType="centerCrop"
                    app:layout_collapseMode="parallax" />

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

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

        </com.example.views.ControllableAppBarLayout>

        <FrameLayout
            android:id="@+id/flContent"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            />

        </com.example.views.MyCoordinatorLayout>


        <!-- DRAWER -->

        <fragment
            android:id="@+id/fDrawer"
            android:name="com.example.fragment.DrawerFragment"
            android:layout_width="@dimen/drawer_width"
            android:layout_height="match_parent"
            android:layout_gravity="left|start"
            android:fitsSystemWindows="true"
            android:clickable="true"
            />

    </android.support.v4.widget.DrawerLayout>

</LinearLayout>

我鼓励您使用带有帮助方法的自定义 AppBarLayout 实现来折叠/展开工具栏。在这个gist 你可以找到一个。

好的,现在是时候在活动中配置我们的工具栏了。

public class ToolbarAppcompatActivity extends AppCompatActivity
        implements AppBarLayout.OnOffsetChangedListener {

    protected Toolbar toolbar;
    protected MyCoordinatorLayout coordinator;
    protected ControllableAppBarLayout appbar;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        configureToolbar();
    switchFragment(new FooFragment(), "FOO", true);
    }

    protected void configureToolbar() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        coordinator = (MyCoordinatorLayout) findViewById(R.id.coordinator);
        appbar = (ControllableAppBarLayout) findViewById(R.id.appbar);
        appbar.addOnOffsetChangedListener(this);
        getDelegate().setSupportActionBar(toolbar);
    }

    public void switchToFragment(Fragment fragment, String tag, boolean expandToolbar){
        FragmentManager fragmentManager = getSupportFragmentManager();

        Fragment currentFragment = fragmentManager.findFragmentByTag(currentFragmentTag);

        if(currentFragment == null || !TextUtils.equals(tag, currentFragmentTag) ){
            currentFragmentTag = tag;
            fragmentManager
                    .beginTransaction()
                    .replace(R.id.flContent, fragment, currentFragmentTag)
                    .commit();

            if(expandToolbar){
                expandToolbar();
            }else{
                collapseToolbar();
            }
        }
    }

    protected void addFragment(Fragment fragment, String tag, boolean expandToolbar) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        currentFragmentTag = tag;
        fragmentManager
                .beginTransaction()
                .add(R.id.flContent, fragment, currentFragmentTag)
                .addToBackStack(tag)
                .commit();

        if(expandToolbar){
            expandToolbar();
        }else{
            collapseToolbar();
        }
    }

   protected void collapseToolbar(){
        appbar.collapseToolbar();
        coordinator.setAllowForScroll(false);
    }

    public void expandToolbar(){
        appbar.expandToolbar();
        coordinator.setAllowForScroll(true);
    }

}

每次你想切换片段和折叠/展开工具栏时 使用适当的布尔参数调用方法 switchFragment/addFragment。

最后一个音符。确保使用最新的支持库。

dependencies {

    // android support
    compile 'com.android.support:appcompat-v7:22.2.1'
    compile 'com.android.support:recyclerview-v7:22.2.1'
    compile 'com.android.support:design:22.2.1'

}

不要在 AppBarLayout 中使用 include 标签。它不起作用

【讨论】:

  • 以防误会。它不是“滚动”,而是“滚动”。无论如何,在 recyclerview 中使用空视图时,扩展 CoordinatorLayout 对我有用。谢谢
【解决方案5】:

以下代码实现了 3 个目标:

禁用 CollapsingToolbarLayout 由用户展开或折叠,但仍允许AppBarLayout.setExpanded

防止滚动 RecyclerView 或 NestedScrollView 展开或折叠 CollapsingToolbarLayout。

// scrollView can be RecyclerView or NestedScrollView
ViewCompat.setNestedScrollingEnabled(scrollView, false)

防止用户通过轻弹 AppBar 来展开或折叠 CollapsingToolbarLayout。

val params = appBar.layoutParams as CoordinatorLayout.LayoutParams
if (params.behavior == null)
    params.behavior = AppBarLayout.Behavior()
val behaviour = params.behavior as AppBarLayout.Behavior
behaviour.setDragCallback(object : AppBarLayout.Behavior.DragCallback() {
    override fun canDrag(appBarLayout: AppBarLayout): Boolean {
        return false
    }
})

https://code.luasoftware.com/tutorials/android/how-to-disable-or-lock-collapsingtoolbarlayout-collapse-or-expand/

【讨论】:

  • 如果使用视图绑定/数据绑定,这似乎不起作用...
  • 非常感谢,这真的拯救了我的一天!我使用 Java 和数据绑定添加了我对您的解决方案的改编:stackoverflow.com/a/69045061/5369519
【解决方案6】:

使用 Android Design Library v23.1.1,@LucyFair 描述的方法不起作用。我设法通过仅将app:layout_scrollFlags 设置为 enterAlwaysCollapsed 来使其工作,并且应用栏保持“锁定”状态。

希望这会有所帮助。 :)

【讨论】:

  • 锁定但展开
【解决方案7】:

我使用了@JasonWyatt的解决方案,并在行为类中添加了DragCallback以防止触摸并拖动CollapsingToolbarLayout来扩展它

private void setDragCallback() {
    setDragCallback(new DragCallback() {
        @Override
        public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
            return mEnabled;
        }
    });
}

【讨论】:

    【解决方案8】:

    我找到了一种适用于活动和各种片段的变通解决方案。您在 Activity 中使用 AppBar 等实现 CollapsingToolbarLayout,然后每次调用新片段时都可以调用这两个函数。

    • 当我希望我的应用栏保持折叠状态时:

      public void lockAppBarClosed() {
          mAppBarLayout.setExpanded(false, false);
          mAppBarLayout.setActivated(false);
          CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams();
          lp.height = (int) getResources().getDimension(R.dimen.toolbar_height);
      }
      
    • 当我希望我的应用栏再次展开和可滚动时

      public void unlockAppBarOpen() {
          mAppBarLayout.setExpanded(true, false);
          mAppBarLayout.setActivated(true);
          CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams();
          lp.height = (int) getResources().getDimension(R.dimen.toolbar_expand_height);
      }
      

    您可以通过实现接口从片段中调用这些函数。这是一个简单的示例,适用于您的情况(工具栏仅在 homeFragment 中扩展)

    public interface CustomListener() {
        void unlockAppBarOpen();
        void lockAppBarClosed()
    }
    
    public class MainActivity extends BaseActivity implements CustomListener {
    
        @Override
        public void unlockAppBarOpen() {
            mAppBarLayout.setExpanded(true, false);
            mAppBarLayout.setActivated(true);
            CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams();
            lp.height = (int) getResources().getDimension(R.dimen.toolbar_expand_height);
        }
    
        @Override
        public void lockAppBarClosed() {
            mAppBarLayout.setExpanded(false, false);
            mAppBarLayout.setActivated(false);
            CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams();
            lp.height = (int) getResources().getDimension(R.dimen.toolbar_height);
        }
    }
    
    public class MainFragment extends BaseFragment {
    
        @Override
        public void onResume() {
            super.onPause();
            ((MainActivity) getContext()).unlockAppBarOpen();
        }
    }
    
    public class SecondFragment extends BaseFragment {
    
        @Override
        public void onResume() {
            super.onPause();
            ((MainActivity) getContext()).lockAppBarClosed();
        }
    }
    

    用这个例子:

    • 每次显示 MainFragment -> 都会扩展工具栏并使其可折叠和可展开

    • 每次显示 SecondFragment -> il 都会将工具栏折叠到标准大小并防止其再次展开

    希望对你有帮助!

    【讨论】:

      【解决方案9】:

      我在 CollapsingToolbarLayout 中找到了启用/禁用折叠的简单解决方案:

          private void setExpandEnabled(boolean enabled) {
              mAppBarLayout.setExpanded(enabled, false);
              mAppBarLayout.setActivated(enabled);
              final AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams();
              if (enabled)
                  params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);
              else
                  params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);
              collapsingToolbarLayout.setLayoutParams(params);
          }
      

      【讨论】:

      • 这不会为我折叠工具栏,但如果我在 setExpanded 之后删除了代码,它肯定会折叠
      • @DasserBasyouni 是的,它不会崩溃。它只是调节 EXPANDED 布局的启用/禁用状态。如果您需要将 Enabled==false 更改为折叠,那么您应该将逻辑中的标志更改为:if (enabled) params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); else params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED); 要折叠的主要标志:SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED
      • 感谢您的回复,但如果工具栏折叠一点,它仍然会展开工具栏,然后它会禁用滚动
      • 这会导致 RecyclerView 在我滚动时几乎不会移动。
      【解决方案10】:

      我无法发表评论,所以我会将我的补充发布到 JasonWyatt'sDisableAppBarLayoutBehavior 解决方案作为独立答案。

      public class DisableableAppBarLayoutBehavior extends AppBarLayout.Behavior {
          private boolean mEnabled = true; // enabled by default
      
          public DisableableAppBarLayoutBehavior() {
              super();
          }
      
          public DisableableAppBarLayoutBehavior(Context context, AttributeSet attrs) {
              super(context, attrs);
          }
      
          public void setEnabled(boolean enabled) {
              mEnabled = enabled;
          }
      
          @Override
          public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes, int type) {
              return mEnabled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes, type);
          }
      
          @Override
          public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
              if (!isEnabled()) return;
              super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
          }
      
          @Override
          public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) {
              if (!isEnabled()) return;
              super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
          }
      
          public boolean isEnabled() {
              return mEnabled;
          }
      }
      

      除了 onStartNestedScroll 还锁定 onNestedPreScrollonNestedScroll 本身以避免意外行为。例如,在我的情况下 - 在我的应用栏上调用 setExpanded(false, true) 会阻碍预期的行为,并且仍然会延迟扩展。现在可以了:

      LayoutParams layoutParams = (LayoutParams) context.appBarLayout.getLayoutParams();
      ((DisableableAppBarLayoutBehavior)layoutParams.getBehavior()).setEnabled(false);
      context.appBarLayout.setLayoutParams(layoutParams);
      context.appBarLayout.setExpanded(false, true); // collapse app bar
      

      【讨论】:

        【解决方案11】:

        除了这个之外,所提供的解决方案都不适合我。使用此解决方案,我可以轻松管理折叠工具栏的状态。这将防止折叠工具栏的展开并为其设置标题。

        public void lockAppBar(boolean locked,String title) {
            if(locked){
                appBarLayout.setExpanded(false, true);
                int px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, getResources().getDisplayMetrics());
                CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appBarLayout.getLayoutParams();
                lp.height = px;
                appBarLayout.setLayoutParams(lp);
                collapsingToolbarLayout.setTitleEnabled(false);
                toolbar.setTitle(title);
            }else{
                appBarLayout.setExpanded(true, false);
                appBarLayout.setActivated(true);
                CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
                lp.height = (int) getResources().getDimension(R.dimen.toolbarExpandHeight);
                collapsingToolbarLayout.setTitleEnabled(true);
                collapsingToolbarLayout.setTitle(title);
            }
        }
        

        【讨论】:

          【解决方案12】:

          像这样找到 AppBarLayout id。

          appBarLayout = (AppBarLayout) findViewById(R.id.appbar);
          

          对某些片段禁用 CollapsingToolbarLayout 的展开

          appBarLayout.setExpanded(true,true);
          

          为某些片段启用 CollapsingToolbarLayout 的展开

          appBarLayout.setExpanded(false,true);
          

          希望对你有帮助!!

          【讨论】:

            【解决方案13】:

            锁定和解锁是不够的,简单的锁定会使图像缩小;这是我的解决方案

            在需要工具栏处于折叠模式的恢复时调用此方法。

            
            private void lockAppBarClosed() {
            
                appBarLayout.setExpanded(false,true);
                CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
                ((CustomAppBarLayoutBehavior)layoutParams.getBehavior()).setScrollBehavior(false);
            
                AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams();
                params.setScrollFlags(0);
                params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);
            
            }
            
            

            这是一个需要Snap的片段

            public void unlockAppBarOpen() {
            
                appBarLayout.setExpanded(true,true);
                CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
                ((CustomAppBarLayoutBehavior)layoutParams.getBehavior()).setScrollBehavior(true);
            
            
                AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams();
                params.setScrollFlags(0);
                params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP);
            
            }
            

            这是一个片段需要在SCROLL_FLAG_EXIT_UNTIL_COLLAPSED模式下滚动。

            
            public void unlockAppBarOpen() {
            
                appBarLayout.setExpanded(true,true);
                CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
                ((CustomAppBarLayoutBehavior)layoutParams.getBehavior()).setScrollBehavior(true);
            
            
                AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams();
                params.setScrollFlags(0);
                params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);
            
            }
            
            

            还有CustomAppBarLayoutBehavior.java

            public class CustomAppBarLayoutBehavior extends AppBarLayout.Behavior {
            
                private boolean shouldScroll = false;
            
                public CustomAppBarLayoutBehavior() {
                    super();
                }
            
                public CustomAppBarLayoutBehavior(Context context, AttributeSet attrs) {
                    super(context, attrs);
                }
            
                @Override
                public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes, int type) {
                    return shouldScroll;
                }
            
                @Override
                public boolean onTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
                    if(shouldScroll){
                        return super.onTouchEvent(parent, child, ev);
                    }else{
                        return false;
                    }
                }
            
                public void setScrollBehavior(boolean shouldScroll){
                    this.shouldScroll = shouldScroll;
                }
            
                public boolean isShouldScroll(){
                    return shouldScroll;
                }
            }
            

            将此行为提供给 AppBarLayout

             <com.google.android.material.appbar.AppBarLayout
                    android:id="@+id/app_bar_layout"
                    android:layout_width="match_parent"
                    android:layout_height="210dp"
                    app:layout_behavior=".behaviors.CustomAppBarLayoutBehavior"
                    android:theme="@style/ThemeOverlay.MaterialComponents.ActionBar.Primary">
            
            

            【讨论】:

              【解决方案14】:

              您可以通过将折叠工具栏高度重置为工具栏高度来锁定 appbarlayout 扩展

              toolbarHeight = toolbar.getLayoutParams().height;
              
              if (expand) {
                  collapsingToolbar.getLayoutParams().height = getResources().getDimensionPixelOffset(R.dimen.collapsingToolbarDefaultHeight);
                  appBarLayout.setExpanded(true, true);
              } else {
                  //collapse
                  //** it is important you do this before resetting **
                  appBarLayout.setExpanded(false, true);
                  appBarLayout.postDelayed(new Runnable() {
                      @Override
                      public void run() {
                          collapsingToolbar.getLayoutParams().height = toolbarHeight;
                      }
                   }, 700/* 600 is default animation time to collapse */);
              }
              

              【讨论】:

                【解决方案15】:

                感谢@Desmond Lua's great answer 我终于能够在我的代码中解决这个问题。这是我使用 Java 和数据绑定的改编解决方案。

                <com.google.android.material.appbar.AppBarLayout
                    android:id="@+id/app_bar"
                    bind:expanded="@{myCondition? false : true}"
                    app:disableCollapsingScroll="@{myCondition? false : true}"
                    ... >
                
                        <com.google.android.material.appbar.CollapsingToolbarLayout
                            ... >
                
                            ...
                
                        </com.google.android.material.appbar.CollapsingToolbarLayout>
                    </com.google.android.material.appbar.AppBarLayout>
                
                <androidx.core.widget.NestedScrollView 
                   android:nestedScrollingEnabled="@{myCondition? false : true}"
                   ... >
                
                   ...
                
                </NestedScrollView>
                
                @BindingAdapter("disableCollapsingScroll")
                public static void bindDisableCollapsingScroll(AppBarLayout appBarLayout, boolean disabled) {
                    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
                
                    if (params.getBehavior() == null) {
                        params.setBehavior(new AppBarLayout.Behavior());
                    }
                
                    AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
                    behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
                        @Override
                        public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
                            return disabled;
                        }
                    });
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-04-20
                  • 2016-08-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-09-24
                  相关资源
                  最近更新 更多