简体   繁体   English

仅针对导航视图中的一个片段折叠工具栏

[英]Collapsing Toolbar only for one Fragment in Navigation View

The Problem问题

I have a navigation drawer with different fragments.我有一个带有不同片段的导航抽屉。 There is a default toolbar every Fragment should use, except of one Fragment which needs a collapsing Toolbar .每个Fragment都应该使用一个默认工具栏,除了一个需要折叠Toolbar Fragment

My Question我的问题

How can I switch between the toolbars for the fragments ?如何在片段的工具栏之间切换?

It seems you want to achieve something like this.看来您想要实现这样的目标。

没有什么花哨

I have made an activity with common toolbar.我做了一个带有通用工具栏的活动。 when switching to the collapsing toolbar fragment I've made the toolbar transparent and fragment's toolbar takes over.当切换到折叠的工具栏片段时,我使工具栏透明,片段的工具栏接管。 The toolbar's color remains the same on switching to other fragments.切换到其他片段时,工具栏的颜色保持不变。

This allows you to manage complete collapsing toolbar's layout structure in xml and logic remains in Fragment.这允许您在 xml 中管理完整的折叠工具栏的布局结构,而逻辑保留在 Fragment 中。

Hope this will help.希望这会有所帮助。 Refer the gif linked.请参阅链接的 gif。

Gist for gif gif 的要点

The best solution that I found to easily collapse, lock it(keep it in collapsed mode) and unlock the collapsingToolbar.我发现可以轻松折叠、锁定(保持折叠模式)并解锁折叠工具栏的最佳解决方案。

private void collapseAppBar() {
    // Collapse the AppBarLayout with animation
    mAppBarLayout.setExpanded(false, true);
}

private void lockAppBar() {
    /* Disable the nestedScrolling to disable expanding the
     appBar with dragging the nestedScrollView below it */
    ViewCompat.setNestedScrollingEnabled(nestedScrollView, false);

    /* But still appBar is expandable with dragging the appBar itself
    and below code disables that too
     */
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
    AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
    behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
        @Override
        public boolean canDrag(AppBarLayout appBarLayout) {
            return false;
        }
    });
}

private void unLockAppBar() {
    ViewCompat.setNestedScrollingEnabled(nestedScrollView, true);

    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
    AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
    if (behavior != null) {
        behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
            @Override
            public boolean canDrag(AppBarLayout appBarLayout) {
                return true;
            }
        });
    }
}

And I use these functions in this way:我以这种方式使用这些功能:

    Fragment fragment = null;
    Class fragmentClass;
    switch (menuItem.getItemId()) {
        case R.id.fragment1:
            unLockAppBar();
            fragmentClass = first_Fragment.class;
            break;
        case R.id.fragment2:
            collapseAppBar();
            lockAppBar();
            fragmentClass = second_Fragment.class;
            break;
        case R.id.fragment3:
            collapseAppBar();
            lockAppBar();
            fragmentClass = third_Fragment.class;
            break;

You can easily get the Toolbar from your Fragment and then modify or change some property of that Toolbar inside the Fragment .您可以轻松地获得Toolbar从你的Fragment ,然后修改或更改的某些属性Toolbar里面Fragment

To get the Toolbar from your Activity you might consider using this.要从您的Activity获取Toolbar ,您可以考虑使用它。

Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);

Now you need to make the changes on the Toolbar in the onResume function and then undo the changes each time you return from the Fragment inside onStop function.现在您需要在onResume函数中的Toolbar上进行更改,然后每次从onStop函数中的Fragment返回时撤消更改。 Otherwise the changes made in the Fragment will be carried on to other fragments as well when switched to other Fragment from the navigation drawer.否则,当从导航抽屉切换到其他Fragment时,在Fragment所做的更改也将继续到其他Fragment

But in your case, I would recommend each Fragment should have their Toolbar so that it doesn't conflict with each other and can be modified as you need.但是在您的情况下,我建议每个Fragment都应该有自己的Toolbar这样它就不会相互冲突,并且可以根据需要进行修改。 And yes, remove the Toolbar from your Activity .是的,从您的Activity删除Toolbar

So add the Toolbar in the layout of your Fragment like this.因此,像这样在Fragment的布局中添加Toolbar

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimaryDark"/>

Then find it in the Fragment然后在Fragment找到它

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment, container, false);
    Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);

    // Modify your Toolbar here. 
    // ... 
    // For example. 
    // toolbar.setBackground(R.color.red);

    // Create home button
    AppCompatActivity activity = (AppCompatActivity) getActivity();
    activity.setSupportActionBar(toolbar);
    activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

And Override the onOptionsItemSelected function.并覆盖onOptionsItemSelected函数。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch(item.getItemId()){
        case android.R.id.home:
            getActivity().onBackPressed();
    }
    return super.onOptionsItemSelected(item);
}

I'm using Jetpack's Navigation components with single Activity and different Fragments in my app.我在我的应用程序中使用Jetpack 的导航组件和单个活动和不同的片段。

Some Fragments are accessible from bottom navigation (and have Toolbar from Activity).一些 Fragments 可以从底部导航访问(并且有来自 Activity 的Toolbar )。 Some others are "special" Fragments and have their own Collapsible Toolbar.其他一些是“特殊”片段,并有自己的可折叠工具栏。

To achieve this, I'm hiding Toolbar from Activity in "special" Fragments with this code in Activity:为了实现这一点,我将工具栏从“特殊”片段中的活动中隐藏起来,并在活动中使用以下代码:

// Handle toolbar changes in different Fragments
val navController = findNavController(R.id.nav_host_fragment)
navController.addOnDestinationChangedListener { _, destination, _ ->
    when (destination.id) {
        R.id.my_special_fragment_with_collapsible_toolbar -> {
            binding.toolbarMain.visibility = View.GONE
        }
        else -> {
            binding.toolbarMain.visibility = View.VISIBLE
        }
    }
}

The recommend practice is to use toolbars in fragments instead of a common toolbar in activity.推荐的做法是在片段中使用工具栏,而不是在活动中使用通用工具栏。 That way you can control the looks and behaviour of toolbar in fragment.这样您就可以在片段中控制工具栏的外观和行为。 Refer https://developer.android.com/guide/navigation/navigation-ui#support_app_bar_variations参考https://developer.android.com/guide/navigation/navigation-ui#support_app_bar_variations

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM