使用工具栏与片段。

48

我正在尝试创建一个能够滑动浏览三个不同片段的视图页面,并且每个片段都有一个不同的工具栏。之前我已经在一个活动中实现了新的工具栏并使其正常工作,但是我现在正试图让它与片段一起使用。

以下是片段代码:

@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的代码,它是否会在某些设备上停止工作?


在您的活动布局中拥有它并在您的活动中设置它是否存在问题? - tachyonflux
1
每个ViewPager的工具栏都将具有不同的颜色和不同的菜单,因此我认为最好使用片段来控制它们。 - Al Hennessey
等一下,这种情况下的整个重点不是ToolBar设置为ActionBar吗?由于您的意图是使每个片段都有自己的ToolBar(与片段的其他内容一起滑动),因此我们谈论该小部件的'独立'用法(向下滚动到“独立”部分)。 - MH.
1
菜单部分已经通过不同的菜单xml文件支持,并通过onCreateOptionsMenu附加。颜色部分可以在onAttach中使用类似于https://dev59.com/moLba4cB1Zd3GeqPZhfu的内容来完成。 - tachyonflux
6个回答

88

Fragment没有setSupportActionBar()这个方法。ActionBar是Activity的属性,所以要将工具栏设置为ActionBar,您的Activity应该扩展自ActionBarActivity,然后在Fragment中调用:

 ((ActionBarActivity)getActivity()).setSupportActionBar(mToolbar);

更新

如果您正在使用AppCompatActivity

 ((AppCompatActivity)getActivity()).setSupportActionBar(mToolbar);

1
在我的情况下,这不会替换Mainactivity的操作栏,但它会像Mainactivity一样为工具栏提供标题。 - Roel
2
@vinitius,你在上面的回答中忘记写“()”在getActivity之后了。所以请添加这个,这样其他人就不会感到困惑了。 - Ram Mansawala
将 SupportActionBar 从 Activity 的工具栏移动到 Fragment 的工具栏可能会失去对 Activity 工具栏的支持。如果您需要在移动了 SupportActionBar 的 Fragment 中更新 Activity 工具栏,该怎么办呢? :) - Faisal Naseer

53

我看到很多答案提到在Fragment中使用setSupportActionBar来设置工具栏,但是如果你的Activity中有一个工具栏和一个独立的在Fragment中的Toolbar,这种方法可能会出错。

  1. 当你将setSupportActionBar从Activity的工具栏转移到Fragment的工具栏时,即使你尝试使用setHasOptionsMenu(true)来进行重写,也可能会遇到MenuItem的重复。
  2. 其次,如果你想要更新Activity的工具栏,你会发现由于Fragment中的setSupportActionBar,你的更改并没有反映出来。

因此为了避免这种情况,我建议在Fragment中使用类似这样的工具栏方法来填充菜单并使用:

 toolbar = (Toolbar) view.findViewById(R.id.toolbar_frag);
    toolbar.inflateMenu(R.menu.frag_menu_items);
    Menu menu = toolbar.getMenu();

使用 Toolbar.OnMenuItemClickListener 接口来接收菜单项的点击事件。

Edit(此部分来源于MrEngineer13的回答

如果你担心返回按钮,可以像这样设置:

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,你能详细解释一下吗?因为我正在遇到你描述的同样的问题。 - Ness Tyagi
你那边有什么问题吗?你尝试过上述方法了吗? - Faisal Naseer
1
我已经通过您的代码解决了问题,感谢您的反馈。实际上,我的应用程序只有一个活动和其他所有片段。因此,在每个片段中更新选项菜单的工具栏会出现问题。但是使用您的代码它可以正常工作,谢谢。 - Ness Tyagi

22
基于@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>

希望它有所帮助。

在此输入图片描述


嗨,展开菜单很好用,但是setOnMenuItemClickListener不起作用。需要帮助。 - a-rohim
即使对于单个菜单,它也显示溢出菜单。我不想要溢出菜单,有什么方法可以实现这一点? - akshay
如果我不想要返回箭头,该怎么隐藏它?我只需要三个点。 - iamkdblue
@Phan,请问BaseFragment在哪里可以给我提供一下吗?因为在这个例子中无法找到toolbar_home - AndyBoy

9
使用新的AppCompatActivity,您应该调用它而不是ActionBarActivity:
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);

2
您可以使用以下方式在Fragment中添加工具栏:

您可以使用以下方法在片段中添加工具栏:

 ((YOUR_ACTIVITY) getActivity()).getDelegate().setSupportActionBar(toolbar);

1
我使用Kotlin。在我的情况下,Activity是AppCompatActivity的子类,活动的主题是从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)
        }
    }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接