需要针对某些片段禁用针对CollapsingToolbarLayout的扩展

Big*_*dad 53 android android-support-library android-toolbar coordinator-layout

我有一个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>
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

tac*_*lux 61

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

recyclerView.setNestedScrollingEnabled(false);
Run Code Online (Sandbox Code Playgroud)

如果您使用支持库,请使用此选项:

ViewCompat.setNestedScrollingEnabled(recyclerView, false);
Run Code Online (Sandbox Code Playgroud)

  • 这不是一个完整的解决方案,因为您仍然可以触摸并拖动CollapsingToolbarLayout来消耗它,它只会禁用带有layout_behavior的NestedScrollView的消耗 (15认同)
  • 实际上,此答案中的 recyclerView 应替换为在 xml 中设置了 layout_behavior 属性的任何视图(或 CoordinatorLayout 中的所有此类视图)。它起作用是因为(至少在支持库的 23.0.1 版中)CoordinatorLayout 的 onStartNestedScroll 方法迭代其子项并询问它们是否接受嵌套滚动。如果没有人接受它,它就不会施展它的滚动魔法。所以,对,可能不需要自定义 CoordinatorLayout,只有辅助方法就足够了(如果有几个孩子有 layout_behavior)。 (2认同)

Jas*_*att 33

此类将允许您禁用/重新启用扩展行为.

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

在您的布局中使用它,如下所示:

<android.support.design.widget.AppBarLayout
    ... other attributes ...
    app:layout_behavior="com.yourpackage.DisableableAppBarLayoutBehavior"
    >
    <!-- your app bar contents -->
</android.support.design.widget.AppBarLayout>
Run Code Online (Sandbox Code Playgroud)

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

AppBarLayout myAppBar = ....;
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) myAppBar.getLayoutParams();
((DisableableAppBarLayoutBehavior) layoutParams.getBehavior()).setEnabled(false);
Run Code Online (Sandbox Code Playgroud)

  • 辛苦了 但是,它具有与上述其他方法相同的问题:您仍然可以通过直接触摸并拖动AppBar本身来扩展内容。 (3认同)

Sev*_*vle 19

现在,在支持库的第23版中,您可以轻松控制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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

编辑: 如果您还想在某些片段中锁定工具栏(除了折叠),您必须求助于解决方法,因为到目前为止,CollapsingToolbarLayout不提供此功能(支持设计的第23.2.1节).在这里,您可以找到我提出的解决方法.

  • 不知道为什么它被接受为答案。当然,这会展开/折叠您的 AppBarLayout,但如果您想_禁用_它,就像问题所说的那样,那么 @tachyonflux 的方法就是正确的选择。 (2认同)

Luc*_*air 11

您所要做的就是将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;
    }
}
Run Code Online (Sandbox Code Playgroud)

活动视图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>
Run Code Online (Sandbox Code Playgroud)

我鼓励您使用自定义AppBarLayout实现和辅助方法来折叠/展开工具栏.在这个要点上你可以找到一个.

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

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

}
Run Code Online (Sandbox Code Playgroud)

每次要切换片段和折叠/展开工具栏时,只需使用适当的布尔参数调用方法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'

}
Run Code Online (Sandbox Code Playgroud)

不要在AppBarLayout中使用include标记.这是行不通的


Des*_*Lua 7

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

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

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

// scrollView can be RecyclerView or NestedScrollView
ViewCompat.setNestedScrollingEnabled(scrollView, false)
Run Code Online (Sandbox Code Playgroud)

防止用户通过轻弹 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
    }
})
Run Code Online (Sandbox Code Playgroud)

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


Str*_*ode 5

使用Android Design Library v23.1.1,@ LucyFair描述的方法不起作用.我设法通过将其设置app:layout_scrollFlagsenterAlwaysCollapsed仅设置来使其工作,并且appbar保持"锁定"状态.

希望这可以帮助.:)

  • 锁定但扩展 (2认同)

小智 5

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

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