需要禁用展开CollapsingToolbarLayout的某些片段

我有一个控制replace很多片段的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> 

我的家庭片段是最初设置,这是我想要的崩溃工具栏扩大,并正常工作。 但是,当我从侧抽屉更改片段我想禁用扩大工具栏。

我已经想出了如何select抽屉项目时将其折叠,但我也需要确保它不展开,除非显示主页片段。 这可能吗?

 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); } } 

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

只需获取对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); } } } 

PS不要忘记在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' } 

编辑:如果你还想要locking您的工具栏在某些片段(除了崩溃),你必须诉诸变通,因为这个function是不是由CollapsingToolbarLayout提供,直到现在(支持devise的v23.2.1)。 在这里你可以find我build议的解决方法。

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

 recyclerView.setNestedScrollingEnabled(false); 

如果您使用支持库,请使用以下方法:

 ViewCompat.setNestedScrollingEnabled(recyclerView, false); 

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

 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); 

所有你需要做的是用CoordinatorLayout的自定义实现replaceCoordinatorLayout,这将欺骗已经处理的嵌套滚动。

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实现与辅助方法来折叠/展开工具栏。 在这个要点上你可以find一个。

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

 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标签。 这是行不通的

使用Androiddevise库v23.1.1,@LucyFair描述的方法不起作用。 我设法通过设置app:layout_scrollFlags来实现它app:layout_scrollFlags enterAlwaysCollapsed只进入enterAlwaysCollapsed ,并且appbar保持“locking”状态。

希望这可以帮助。 🙂

我find了解决scheme,可以处理活动和各种片段。 您可以在您的活动中使用AppBar等实现CollapsingToolbarLayout,然后每次调用新的片段时都可以调用这两个函数。

  • 当我想要我的appbar保持折叠:

     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); } 
  • 当我想要我的appbar被扩展和再滚动

     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会将工具栏折叠为标准大小,并防止再次展开

希望它会帮助你!

我发现简单的解决scheme来启用/禁用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); } 

我已经使用了@JasonWyatt的解决scheme,并将DragCallback添加到行为类,以防止触摸并拖动CollapsingToolbarLayout来展开它

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

我不能发表评论,所以我会把我的补充发布到JasonWyatt的 DisableableAppBarLayoutBehavior解决scheme作为独立的答案。

 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外,还会lockingNestedPreScrollonNestedScroll本身,以避免意外的行为。 例如,就我而言在我的应用程序栏上调用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 

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

 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); } }