带有导航组件的顶部应用程序栏和底部应用程序栏有两个不同的菜单 [英] Two different menus for Top App Bar and Bottom App bar with Navigation Components

查看:123
本文介绍了带有导航组件的顶部应用程序栏和底部应用程序栏有两个不同的菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在试用Android 导航架构组件,并且查看材料设计指南.我真的受到

I was trying out Android Navigation Architecture Component and was also looking into Material design guidelines. I really got inspired by the design below:

对于顶部工具栏,我可以通过setSupportActionBar(toolbar)进行设置,然后在MainActivity中进行设置:

For the top toolbar I can set it by setSupportActionBar(toolbar) and then in MainActivity:

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);
    return super.onCreateOptionsMenu(menu);
}

但是在尝试时,我无法弄清楚如何在顶部和底部应用程序栏上实现不同片​​段的菜单,特别是底部应用程序栏.

But while trying it out I cannot figure it out how to implement menus on both Top and Bottom app bars for different fragments, specially for bottom app bar.

例如,我只想在DetailFragment上的底部应用栏上显示 最喜欢的图标 ,但在MainActivity上显示,它应该消失了.

For example, I want to show a favorite icon on bottom app bar only on DetailFragment, but on MainActivity, it should be gone.

我当前的代码:

MainActivity

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        NavController navController = Navigation.findNavController(this, R.id.nav_host);
        NavigationUI.setupActionBarWithNavController(this, navController);


        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(view -> Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                .setAction("Action", null).show());


    }

    @Override
    public boolean onSupportNavigateUp() {
        return Navigation.findNavController(this, R.id.nav_host).navigateUp();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return super.onCreateOptionsMenu(menu);
    }
}

MainFragment

public class MainFragment extends Fragment {

    public MainFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_main, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Button buttonOne = view.findViewById(R.id.button_one);
        buttonOne.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.detailFragment));
    }

}

DetailFragment

public class DetailFragment extends Fragment {

    public DetailFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_detail, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:animateLayoutChanges="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </com.google.android.material.appbar.AppBarLayout>

    <fragment
        android:id="@+id/nav_host"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="top"
        android:layout_marginTop="?android:attr/actionBarSize"
        app:defaultNavHost="true"
        app:layout_anchor="@id/bottom_appbar"
        app:layout_anchorGravity="top"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        app:navGraph="@navigation/mobile_navigation" />

    <com.google.android.material.bottomappbar.BottomAppBar
        android:id="@+id/bottom_appbar"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/actionBarSize"
        android:layout_gravity="bottom" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_anchor="@id/bottom_appbar" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

mobile_navigation.xml

mobile_navigation.xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mobile_navigation"
    app:startDestination="@id/mainFragment">
    <fragment
        android:id="@+id/mainFragment"
        android:name="com.example.MainFragment"
        android:label="fragment_main"
        tools:layout="@layout/fragment_main" >
        <action
            android:id="@+id/toAccountFragment"
            app:destination="@id/detailFragment" />
    </fragment>
    <fragment
        android:id="@+id/detailFragment"
        android:name="com.example.DetailFragment"
        android:label="fragment_account"
        tools:layout="@layout/fragment_detail" />
</navigation>

menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/app_bar_settings"
        android:title="@string/action_settings"
        app:showAsAction="never" />
</menu>

bottom_appbar_menu.xml 仅用于DetialFragment

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/action_bottom_fav"
        android:icon="@drawable/ic_favorite"
        android:title="@string/action_favorite"
        app:showAsAction="ifRoom" />
</menu>

感谢您的帮助.

这是我能想到的,但是我不满意,因为我不知道这是否是写方法.我正在发布一个可能的解决方案:

This is what I'm able to come up with but is not satisfied as I don't know if it's the write way to do it. I'm posting a possible solution:

1- MainActivity

1- MainActivity

NavController navController = Navigation.findNavController(this, R.id.nav_host);
NavigationUI.setupWithNavController(toolbar, navController);

2-为底部应用栏创建两个不同的菜单(我没有尝试动态添加菜单项),一个菜单的MainFragment带有空白的菜单xml,另一个菜单的DetailFragment包含一个喜欢的图标.

2- Creating two different menus for bottom app bar (I didn't tried adding menu items dynamically), one with a blank menu xml for MainFragment and another one that contains a favorite icon for DetailFragment.

为简单起见,请在MainActivity中覆盖onCreateOptionsMenu,而不是用MainFragment覆盖:

For simplicity, overriding onCreateOptionsMenu in MainActivity rather than overriding it with the MainFragment:

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);
    bottomAppBar.replaceMenu(R.menu.bottom_menu_blank);
    return super.onCreateOptionsMenu(menu);
}

3-感谢 @ʍѳђઽ૯ท,让我了解了Bottom App Bar的replaceMenu方法.在DetailFragment中使用setHasOptionsMenu(true)并覆盖onCreateOptionsMenu:

3- Thanks to @ʍѳђઽ૯ท for letting me know about replaceMenu method of Bottom App Bar. In DetailFragment use setHasOptionsMenu(true) and override onCreateOptionsMenu:

public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    BottomAppBar bottomAppBar = requireActivity().findViewById(R.id.bottom_appbar);
    bottomAppBar.replaceMenu(R.menu.bottom_menu_fav);
}

如果有人有更好的方法,请告诉我们.

If anyone has a better way then please do let know.

推荐答案

只需像往常一样对Toolbar使用onCreateOptionsMenu():(科特林)

Just use onCreateOptionsMenu() for the Toolbar as usual: (Kotlin)

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.menu_first, menu)
        return super.onCreateOptionsMenu(menu)
    }

然后在onCreate()内声明Toolbar并使用setSupportActionBar():

val toolbar = findViewById<Toolbar>(R.id.myToolbar)
setSupportActionBar(toolbar)

然后,replaceMenu()将完成操作:(在onCreate()内部)

And after that, replaceMenu() will do the trick: (Inside onCreate())

val bottomBar = findViewById<BottomAppBar>(R.id.bottomAppBar)
bottomBar.replaceMenu(R.menu.menu_main)


请注意,如果您想使用BottomSheetFragment作为NavigationView的开头,则需要setSupportActionBar才能为BottomAppBar设置menu s,但我仍然找不到找到方法解决这个问题.


Note that if you wanted to use BottomSheetFragment for the NavigationView opening, you'll need setSupportActionBar in order to set menus for the BottomAppBar and I couldn't still find a way to fix this.

这篇关于带有导航组件的顶部应用程序栏和底部应用程序栏有两个不同的菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆