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

Posted

技术标签:

【中文标题】需要为某些片段禁用 CollapsingToolbarLayout 上的展开【英文标题】:Need to disable expand on CollapsingToolbarLayout for certain fragments 【发布时间】: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_
android:layout_
android:fitsSystemWindows="true">

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

<android.support.design.widget.NavigationView
    android:id="@+id/navigation_view"
    android:layout_
    android:layout_
    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_
    android:layout_
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_
        android:layout_
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_
            android:layout_
            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_
                android:layout_
                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_
                android:layout_
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin"/>

            <android.support.design.widget.TabLayout
                android:id="@+id/tabs"
                android:layout_
                android:layout_
                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_
        android:layout_
        app:layout_behavior="@string/appbar_scrolling_view_behavior" >
    </FrameLayout>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab1"
        android:layout_
        android:layout_
        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);
        
    

【问题讨论】:

你有没有找到办法做到这一点?我遇到了同样的问题。 不。我不得不放弃这个概念并将其删除。我认为折叠工具栏不应该与片段一起使用 也许这会有所帮助:***.com/a/53433716/878126? 【参考方案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_
    android:layout_
    android:orientation="vertical"
    >

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

        <!--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_
            android:layout_
            android:fitsSystemWindows="true"
            >

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

            <android.support.design.widget.CollapsingToolbarLayout
                android:id="@+id/collapsing_toolbar"
                android:layout_
                android:layout_
                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_
                    android:layout_
                    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_
                    android:layout_
                    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_
            android:layout_
            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_
            android:layout_
            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 和数据绑定添加了我对您的解决方案的改编:***.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_
        android:layout_
        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;
        
    );

【讨论】:

以上是关于需要为某些片段禁用 CollapsingToolbarLayout 上的展开的主要内容,如果未能解决你的问题,请参考以下文章

Eclipse 自动创建片段布局,我该如何禁用它

在 laravel 5.4 中为某些路由禁用 csrf 令牌?不工作[重复]

为啥保守光栅化无法为某些三角形调用片段着色器?

根据活动(即可见)片段以编程方式启用或禁用按钮

如何在 Hibernate 中为某些实体禁用模式验证?

片段交易后如何禁用按钮?