如何从片段获取工具栏?

119
我有一个带有导航抽屉和使用support_v7工具栏的ActionBarActivity。在我的一个片段中,工具栏有自定义视图。在其他片段中,工具栏应显示标题。如何从片段获取工具栏实例以进行自定义设置?我可以使用getActivity().getActionBar()获取ActionBar,但如果我为此实例ActionBar调用setTitle(),它不起作用。 UPD: 在我的情况下, ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(); (就像MrEngineer13所说的那样)在第一次创建片段时无法正常工作,因为我是从onHiddenChanged()中调用它的。现在我在onCreateView()中添加了一个内容,它可以正常工作。

碎片没有操作栏/工具栏活动。 - tyczj
1
(MainAcivity)this.getActivity())。getToolbar(); 将是在片段中获取工具栏的正确答案!! - LOG_TAG
10个回答

221

你需要先将你的活动从 getActivity() 转换为 AppCompatActivity。这里是一个例子:

((AppCompatActivity) getActivity()).getSupportActionBar().setTitle();

你需要进行类型转换是因为getActivity()返回的是FragmentActivity类型,而你需要的是一个AppCompatActivity类型。

Kotlin中的写法:

(activity as AppCompatActivity).supportActionBar?.title = "My Title"

9
“getting 'supportActionBar' and 'toolbar' is same thing?” 的翻译是:“获取 'supportActionBar' 和 'toolbar' 是同一件事吗?” - Darpan
@Darpan 不确定 - Konstantin Konopko
如果我添加这个,它会改变标题..但是如果我回到父活动,如何再次更改标题?我的意思是我有一个导航抽屉。侧边抽屉有一些片段,主要活动有自己的标题。当我设置主要活动的标题时,它可以工作,并且在片段中,您提到的方式完美地工作。但是我应该如何在返回时更改活动的标题? - Kylo Ren

85

如果片段应具有自定义的工具栏视图,则可以为每个片段单独实现工具栏。

将工具栏添加到 fragment_layout 中:

<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"/>

在片段中查找:

@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);

        //set toolbar appearance
        toolbar.setBackground(R.color.material_blue_grey_800);

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

菜单监听器可以通过两种方式创建: 在您的片段中覆盖onOptionsItemSelected:

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

或者在onCreateView()中创建工具栏时为其设置监听器:

toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                return false;
            }
        });

1
我只是想确认这样做的正确性?如果我们在ViewPager + TabLayout或PagerTabStrip中加载不同的片段与工具栏,是否会影响应用程序在滑动时的性能? - LOG_TAG
1
@LOG_TAG 我有一个抽屉设计,每个片段都实现了工具栏(因此在其布局文件中有一个工具栏),上面的代码对我非常有效。 - MattBoothDev
谢谢!像 HEYUL 一样有效!! :) 另外,为了避免重复代码,最好覆盖父 Activity 的 onOptionsItemSelected() 方法,而不是 Fragment 的。 - Aditya Naique
@ChadMx 不是的,他为什么要写关于在xml中添加工具栏之类的内容呢。作者问如何从片段程序中以编程方式获取工具栏。因此,https://dev59.com/IF8d5IYBdhLWcg3wTAl-#26998718 这是最好/正确的答案,而且很简短。 - user25

51

您有两个选择来在Fragment中获取工具栏

第一个选择

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

和第二个

Toolbar toolbar = ((MainActivity) getActivity()).mToolbar;

但这是正确的方式吗?因为我们还有getSupportedActionBar呢? - Code_Life
2
如果您正在使用一种活动对多个片段的模型,则第一个示例仅会为您获取对主工具栏的引用,以便您可以从片段中进行操作。我认为这也是最佳选择。 - Trasd

10
toolbar = (Toolbar) getView().findViewById(R.id.toolbar);
AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.setSupportActionBar(toolbar);

2
对于 Kotlin 用户来说,(activity as AppCompatActivity).supportActionBar?.show() 的意思是“显示应用程序栏”。其中,“?”表示如果应用程序栏不为空,则执行该操作。

使用 ? 完全可以避免 !!,并且可以避免可能的崩溃。 - JonZarate
1
我相信这样写更好 (activity as? AppCompatActivity)?.supportActionBar?.show() - JonZarate

2

从你的Fragment中:(如何从fragment中获取工具栏?)

// get toolbar
((MainAcivity)this.getActivity()).getToolbar();  // getToolbar will be method in Activity that returns Toolbar!!  don't use getSupportActionBar for getting toolbar!!
// get action bar
this.getActivity().getSupportActionBar();
这非常有用,特别是当你在工具栏中使用下拉框(spinner)并从片段中调用工具栏中的 spinner 或自定义视图时!

从你的活动:

// get toolbar
this.getToolbar();
// get Action Bar
this.getSupportActionBar();

3
你的活动中必须有一个名为 getToolbar() 的方法,这样做是不好的,因为这不是活动和片段之间通信的正确方式。 - Marko
2
是的,没有其他方法可以解决这个问题!!!许多导航抽屉库只实现了这种样式!!!有时我们需要转换活动,因为 AppCompatActivity (AppCompatActivity) getActivity() 这是另一个痛点!!!所有这些东西都会完全浪费开发时间:( - LOG_TAG

1

如果你正在使用support_v7,那么你可能需要尝试getActivity().getSupportActionBar().setTitle()


1

我是通过以下步骤完成的。

  1. 在主要片段的onCreateView中使用下面的代码设置标题。
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("Your title");

  • 对于在片段之间切换,我使用了底部导航栏,它是在片段的父活动MainActivity中实现的。即使您使用任何按钮或菜单项,也可以从onSelectedItemClickListener更改标题,就像我在我的情况下所做的那样。
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        switch (menuItem.getItemId()){
            case R.id.menu_dashboard:
                getSupportActionBar().setTitle("仪表盘");
                fm.beginTransaction().hide(active).show(dashboardFragment).commit();
                active = dashboardFragment;
                return true;
            case R.id.menu_workshop:
                getSupportActionBar().setTitle("工作坊");
                fm.beginTransaction().hide(active).show(workshopFragment).commit();
                active = workshopFragment;
                return true;
         }
         return false;
    }
    

  • 1

    在XML中

     <androidx.appcompat.widget.Toolbar
      android:id="@+id/main_toolbar"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      app:layout_scrollFlags="scroll|enterAlways">
     </androidx.appcompat.widget.Toolbar>
    
    Kotlin: 在 fragment.kt 文件中 -> onCreateView() 方法
    setHasOptionsMenu(true)
    
    val toolbar = view.findViewById<Toolbar>(R.id.main_toolbar)
    
    (activity as? AppCompatActivity)?.setSupportActionBar(toolbar)
    
    (activity as? AppCompatActivity)?.supportActionBar?.show()
    

    -> onCreateOptionsMenu()

       override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
           inflater.inflate(R.menu.app_main_menu,menu)
           super.onCreateOptionsMenu(menu, inflater)
       }
    

    ->onOptionsItemSelected()

       override fun onOptionsItemSelected(item: MenuItem): Boolean {
            return when (item.itemId) {
                 R.id.selected_id->{//to_do}
                 else -> super.onOptionsItemSelected(item)
            }
        }
    

    0

    如果您正在使用自定义工具栏或操作栏,并且您想从片段获取工具栏/操作栏的引用,则需要先从片段的onCreateView方法中获取主活动的实例,如下所示。

    MainActivity activity = (MainActivity) getActivity();
    

    然后像下面这样使用活动进行进一步的实现

    ImageView vRightBtn = activity.toolbar.findViewById(R.id.toolbar_right_btn);
    

    在调用此方法之前,您需要在MainActivity中初始化自定义工具栏,如下所示。

    首先,将您的工具栏设置为公共的,例如:

    public Toolbar toolbar;
    public ActionBar actionBar;
    
    在编程中,在onCreate()方法中分配自定义工具栏ID。
    toolbar = findViewById(R.id.custom_toolbar);
    setSupportActionBar(toolbar);
    actionBar = getSupportActionBar();
    

    就是这样。它将在Fragment中运行。


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