问题描述
我正在试用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 menu
s for the BottomAppBar
and I couldn't still find a way to fix this.
这篇关于带有导航组件的顶部应用程序栏和底部应用程序栏有两个不同的菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!