将工具栏与片段一起使用
Using Toolbar with Fragments
我正在尝试创建一个 viewpager,它可以在 3 个不同的片段中滑动,每个片段都有不同的工具栏。我之前在 activity 中实现了新的工具栏并让它工作但是我试图让它与片段一起工作
这是片段代码
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout resource that'll be returned
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
mToolbar = (Toolbar) rootView.findViewById(R.id.toolbar_home);
if (mToolbar != null) {
setSupportActionBar(mToolbar);
}
mToolbar.setTitle(null);
return rootView;
}
我正在使用 Fragment
扩展我的片段,但是我收到了错误
Cannot resolve method setSupportActionBar
我不确定如何解决这个问题,如果我删除 setSupportActionBar
代码,它会停止在某些设备上工作吗?
Fragments没有这样的方法setSupportActionBar()
。 ActionBar 是 Activity 的 属性,因此要将您的工具栏设置为 actionBar,您的 activity 应该从 ActionBarActivity 扩展,然后您可以调用您的 Fragment:
((ActionBarActivity)getActivity()).setSupportActionBar(mToolbar);
更新
如果您正在使用 AppCompatActivity:
((AppCompatActivity)getActivity()).setSupportActionBar(mToolbar);
对于新的 AppCompatActivity,您应该调用它而不是 ActionBarActivity:
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
您可以使用这个在 Fragments 中添加工具栏
((YOUR_ACTIVITY) getActivity()).getDelegate().setSupportActionBar(toolbar);
我看到很多答案都提到 setSupportActionBar
用于 Fragment
中的工具栏,但是如果您在 Activity
中有一个工具栏和一个单独的 Toolbar
在 Fragment
中。
- 当您将
setSupportActionBar
从 Activity 的工具栏转移到 Fragment 的工具栏时,您可能会面临 MenuItem
的重复,即使您尝试使用 setHasOptionsMenu(true)
覆盖。
- 其次,如果您想更新 Activity 的工具栏,您会发现您的更改没有反映出来,因为
setSupportActionBar
在您的 Fragment 中。
因此,为了避免这种情况,我建议在片段中使用像这样的工具栏方法来扩充菜单并使用
toolbar = (Toolbar) view.findViewById(R.id.toolbar_frag);
toolbar.inflateMenu(R.menu.frag_menu_items);
Menu menu = toolbar.getMenu();
并使用 Toolbar.OnMenuItemClickListener
接口接收 menuItems 点击事件。
编辑(从MrEngineer13 answer复制的部分)
如果您担心后退按钮,您可以这样设置
toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_action_back));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//What to do on back clicked
}
});
基于@Faisal Naseer 的回答。这是使用自定义 Toolbar
的完整示例(带有一些注释)
导航和菜单在Fragment
fragment_home.xml
<androidx.constraintlayout.widget.ConstraintLayout 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"">
...
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar_home"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="Home" />
</androidx.constraintlayout.widget.ConstraintLayout>
HomeFragment.kt
class HomeFragment : BaseFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
// setHasOptionsMenu(true): don't need this anymore
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
toolbar_home.setNavigationIcon(R.drawable.ic_back) // need to set the icon here to have a navigation icon. You can simple create an vector image by "Vector Asset" and using here
toolbar_home.setNavigationOnClickListener {
// do something when click navigation
}
toolbar_home.inflateMenu(R.menu.menu_home)
toolbar_home.setOnMenuItemClickListener {
when (it.itemId) {
R.id.action_add -> {
// do something
true
}
R.id.action_update -> {
// do something
true
}
else -> {
super.onOptionsItemSelected(it)
}
}
}
}
}
menu_home.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_add"
android:title="@string/add_device"
app:showAsAction="never" />
<item
android:id="@+id/action_update_room"
android:title="@string/update_room"
app:showAsAction="never" />
</menu>
希望对您有所帮助
我使用 Kotlin。在我的例子中 Activity 是 AppCompatActivity 的子 class 并且 activity 的主题继承自
Theme.MaterialComponents.DayNight.NoActionBar
所以我的 Activity 没有操作栏,但我的 Fragment 有。
我将向您展示如何使用带有定义菜单的工具栏作为片段中的 SupportActionBar
这是我的工具栏
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:fitsSystemWindows="true"
app:navigationContentDescription="Back to the previous question"
android:background="?attr/colorPrimary"
tools:title="@string/posts" />
这是我的 Fragment 的方法:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(context as AppCompatActivity).setSupportActionBar(_bind?.toolbar)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.toolbar_menu_post_list, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when(item.itemId)
{
R.id.add -> {
val post = Post()
postListViewModel.addPost(post)
callbacks?.onItemSelected(post.id)
return true
}
else -> super.onOptionsItemSelected(item)
}
}
我正在尝试创建一个 viewpager,它可以在 3 个不同的片段中滑动,每个片段都有不同的工具栏。我之前在 activity 中实现了新的工具栏并让它工作但是我试图让它与片段一起工作
这是片段代码
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout resource that'll be returned
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
mToolbar = (Toolbar) rootView.findViewById(R.id.toolbar_home);
if (mToolbar != null) {
setSupportActionBar(mToolbar);
}
mToolbar.setTitle(null);
return rootView;
}
我正在使用 Fragment
扩展我的片段,但是我收到了错误
Cannot resolve method setSupportActionBar
我不确定如何解决这个问题,如果我删除 setSupportActionBar
代码,它会停止在某些设备上工作吗?
Fragments没有这样的方法setSupportActionBar()
。 ActionBar 是 Activity 的 属性,因此要将您的工具栏设置为 actionBar,您的 activity 应该从 ActionBarActivity 扩展,然后您可以调用您的 Fragment:
((ActionBarActivity)getActivity()).setSupportActionBar(mToolbar);
更新
如果您正在使用 AppCompatActivity:
((AppCompatActivity)getActivity()).setSupportActionBar(mToolbar);
对于新的 AppCompatActivity,您应该调用它而不是 ActionBarActivity:
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
您可以使用这个在 Fragments 中添加工具栏
((YOUR_ACTIVITY) getActivity()).getDelegate().setSupportActionBar(toolbar);
我看到很多答案都提到 setSupportActionBar
用于 Fragment
中的工具栏,但是如果您在 Activity
中有一个工具栏和一个单独的 Toolbar
在 Fragment
中。
- 当您将
setSupportActionBar
从 Activity 的工具栏转移到 Fragment 的工具栏时,您可能会面临MenuItem
的重复,即使您尝试使用setHasOptionsMenu(true)
覆盖。 - 其次,如果您想更新 Activity 的工具栏,您会发现您的更改没有反映出来,因为
setSupportActionBar
在您的 Fragment 中。
因此,为了避免这种情况,我建议在片段中使用像这样的工具栏方法来扩充菜单并使用
toolbar = (Toolbar) view.findViewById(R.id.toolbar_frag);
toolbar.inflateMenu(R.menu.frag_menu_items);
Menu menu = toolbar.getMenu();
并使用 Toolbar.OnMenuItemClickListener
接口接收 menuItems 点击事件。
编辑(从MrEngineer13 answer复制的部分)
如果您担心后退按钮,您可以这样设置
toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_action_back));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//What to do on back clicked
}
});
基于@Faisal Naseer 的回答。这是使用自定义 Toolbar
的完整示例(带有一些注释)
导航和菜单在Fragment
fragment_home.xml
<androidx.constraintlayout.widget.ConstraintLayout 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"">
...
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar_home"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="Home" />
</androidx.constraintlayout.widget.ConstraintLayout>
HomeFragment.kt
class HomeFragment : BaseFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
// setHasOptionsMenu(true): don't need this anymore
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
toolbar_home.setNavigationIcon(R.drawable.ic_back) // need to set the icon here to have a navigation icon. You can simple create an vector image by "Vector Asset" and using here
toolbar_home.setNavigationOnClickListener {
// do something when click navigation
}
toolbar_home.inflateMenu(R.menu.menu_home)
toolbar_home.setOnMenuItemClickListener {
when (it.itemId) {
R.id.action_add -> {
// do something
true
}
R.id.action_update -> {
// do something
true
}
else -> {
super.onOptionsItemSelected(it)
}
}
}
}
}
menu_home.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_add"
android:title="@string/add_device"
app:showAsAction="never" />
<item
android:id="@+id/action_update_room"
android:title="@string/update_room"
app:showAsAction="never" />
</menu>
希望对您有所帮助
我使用 Kotlin。在我的例子中 Activity 是 AppCompatActivity 的子 class 并且 activity 的主题继承自 Theme.MaterialComponents.DayNight.NoActionBar
所以我的 Activity 没有操作栏,但我的 Fragment 有。
我将向您展示如何使用带有定义菜单的工具栏作为片段中的 SupportActionBar
这是我的工具栏
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:fitsSystemWindows="true"
app:navigationContentDescription="Back to the previous question"
android:background="?attr/colorPrimary"
tools:title="@string/posts" />
这是我的 Fragment 的方法:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(context as AppCompatActivity).setSupportActionBar(_bind?.toolbar)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.toolbar_menu_post_list, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when(item.itemId)
{
R.id.add -> {
val post = Post()
postListViewModel.addPost(post)
callbacks?.onItemSelected(post.id)
return true
}
else -> super.onOptionsItemSelected(item)
}
}