99

在我的 MainFragmentActivity中,我设置了我的自定义ActionBar标题,如下所示:

    LayoutInflater inflator = (LayoutInflater) this
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = inflator.inflate(R.layout.custom_titlebar, null);

    TextView tv = (TextView) v.findViewById(R.id.title);
    Typeface tf = Typeface.createFromAsset(this.getAssets(),
            "fonts/capsuula.ttf");
    tv.setTypeface(tf);
    tv.setText(this.getTitle());

    actionBar.setCustomView(v);

这很完美。但是,一旦我打开 other Fragments,我希望标题改变。我不确定如何访问 MainActivity来执行此操作?过去,我是这样做的:

((MainFragmentActivity) getActivity()).getSupportActionBar().setTitle(
            catTitle);

有人可以建议正确的方法吗?

XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent" >

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:text=""
        android:textColor="#fff"
        android:textSize="25sp" />

</RelativeLayout>
4

22 回答 22

153

你在做什么是正确的。Fragments无权访问ActionBarAPI,因此您必须调用getActivity. 除非你Fragment是一个静态内部类,在这种情况下你应该创建一个WeakReference父类并调用 Activity。getActionBar从那里。

ActionBar要在使用自定义布局时为您的 设置标题,您Fragment需要调用getActivity().setTitle(YOUR_TITLE).

你打电话的原因setTitle是因为你打电话getTitle作为你的ActionBar. getTitle返回那个的标题Activity

如果您不想拨打电话getTitle,那么您需要创建一个公共方法来设置您TextViewActivity托管Fragment.

在您的活动中

public void setActionBarTitle(String title){
    YOUR_CUSTOM_ACTION_BAR_TITLE.setText(title);
}

在你的片段中

((MainFragmentActivity) getActivity()).setActionBarTitle(YOUR_TITLE);

文件:

Activity.getTitle

Activity.setTitle

此外,您不需要调用this.whatever您提供的代码,只是一个提示。

于 2013-03-22T01:09:11.693 回答
105

===2019 年 10 月 30 日更新===

由于我们有了ViewModelLiveData等新组件,我们可以通过使用 ViewModel 和 Live Data 以不同/更简单的方式从 Fragment 更新 Activity Title

活动

class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_activity)
    if (savedInstanceState == null) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.container, MainFragment.newInstance())
            .commitNow()
    }
    viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
    viewModel.title.observe(this, Observer {
        supportActionBar?.title = it
    })
} }

主要片段

class MainFragment : Fragment() {
companion object {
    fun newInstance() = MainFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View {
    return inflater.inflate(R.layout.main_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    activity?.run {
        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
    } ?: throw Throwable("invalid activity")
    viewModel.updateActionBarTitle("Custom Title From Fragment")
} }

和 MainModelView:

class MainViewModel : ViewModel() {
private val _title = MutableLiveData<String>()
val title: LiveData<String>
get() = _title
fun updateActionBarTitle(title: String) = _title.postValue(title) }

然后您可以使用 Fragment 更新活动标题viewModel.updateActionBarTitle("Custom Title From Fragment")

===2015 年 4 月 10 日更新===

您应该使用侦听器来更新您的操作栏标题

分段:

public class UpdateActionBarTitleFragment extends Fragment {
    private OnFragmentInteractionListener mListener;

    public UpdateActionBarTitleFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (mListener != null) {
            mListener.onFragmentInteraction("Custom Title");
        }
        return inflater.inflate(R.layout.fragment_update_action_bar_title2, container, false);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        public void onFragmentInteraction(String title);
    }
}

和活动:

public class UpdateActionBarTitleActivity extends ActionBarActivity implements UpdateActionBarTitleFragment.OnFragmentInteractionListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_update_action_bar_title);
    }

    @Override
    public void onFragmentInteraction(String title) {
        getSupportActionBar().setTitle(title);
    }
}

在此处阅读更多信息:https ://developer.android.com/training/basics/fragments/communicating.html

于 2013-08-02T07:56:57.687 回答
31

谷歌示例倾向于在片段中使用它。

private ActionBar getActionBar() {
    return ((ActionBarActivity) getActivity()).getSupportActionBar();
}

该片段将属于一个 ActionBarActivity ,这就是对操作栏的引用所在。这样更简洁,因为片段不需要确切知道它是什么活动,它只需要属于实现了 ActionBarActivity 的活动。这使片段更加灵活,并且可以添加到多个活动中,就像它们应该做的那样。

现在,您需要在片段中做的就是。

getActionBar().setTitle("Your Title");

如果您有一个片段继承自基础片段而不是普通片段类,则此方法效果很好。

public abstract class BaseFragment extends Fragment {
    public ActionBar getActionBar() {
        return ((ActionBarActivity) getActivity()).getSupportActionBar();
    }
}

然后在你的片段中。

public class YourFragment extends BaseFragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getActionBar().setTitle("Your Title");
    }
}
于 2014-03-05T18:00:21.557 回答
9

我不认为接受的答案是一个完美的答案。由于所有使用的活动

工具栏

扩展使用

AppCompatActivity

,从中调用的片段可以使用下面提到的代码来更改标题。

((AppCompatActivity) context).getSupportActionBar().setTitle("Your Title");
于 2018-01-16T10:20:47.377 回答
8

设置Activity's title from aFragment混乱的责任级别。Fragment包含在一个Activity中,所以这是Activity,它应该根据例子的类型设置自己的标题Fragment

假设你有一个接口:

interface TopLevelFragment
{
    String getTitle();
}

Fragment可以影响Activity' 标题的 s 则实现该接口。在托管活动中,您编写:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FragmentManager fm = getFragmentManager();
    fm.beginTransaction().add(0, new LoginFragment(), "login").commit();
}

@Override
public void onAttachFragment(Fragment fragment)
{
    super.onAttachFragment(fragment);

    if (fragment instanceof TopLevelFragment)
        setTitle(((TopLevelFragment) fragment).getTitle());
}

以这种方式Activity始终可以控制要使用的标题,即使TopLevelFragment组合了几个 s,这在平板电脑上是完全可能的。

于 2015-07-23T09:17:28.273 回答
8

一个简单的 Kotlin 示例

将此适应您的片段类:

    /**
     * A simple [Fragment] subclass.
     *
     * Updates the action bar title when onResume() is called on the fragment,
     * which is called every time you navigate to the fragment
     *
     */

    class MyFragment : Fragment() {

        override fun onResume() {
            super.onResume()
            (requireActivity() as MyMainActivity).supportActionBar?.title = "My Fragment!"
        }


    }
于 2019-08-25T06:52:48.000 回答
5

在我们可以这样使用的片段中,它对我来说很好用。

getActivity().getActionBar().setTitle("YOUR TITLE");
于 2015-02-09T08:27:39.450 回答
4

以防万一您对代码有疑问,请尝试将其放入 getSupportActionBar().setTitle(title)片段onResume()而不是onCreateView(...)ie

MainActivity.java中:

public void setActionBarTitle(String title) {
    getSupportActionBar().setTitle(title);
}

在片段中:

 @Override
 public void onResume(){
     super.onResume();
     ((MainActivity) getActivity()).setActionBarTitle("Your Title");
 }
于 2017-08-04T14:08:12.020 回答
3

使用以下内容:

getActivity().setTitle("YOUR_TITLE");
于 2014-09-15T05:20:56.613 回答
2

这是我在使用 NavigationDrawer 时从片段中设置 ActionBar 标题的解决方案。此解决方案使用接口,因此片段不需要直接引用父 Activity:

1)创建接口:

public interface ActionBarTitleSetter {
    public void setTitle(String title); 
}

2) 在 Fragment 的onAttach中,将活动转换为 Interface 类型并调用 SetActivityTitle 方法:

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity);
    ((ActionBarTitleSetter) activity).setTitle(getString(R.string.title_bubbles_map)); 
}

3)在activity中,实现ActionBarTitleSetter接口:

@Override 
public void setTitle(String title) { 
    mTitle = title; 
}
于 2015-02-02T13:57:04.437 回答
2

更改标题的最佳事件onCreateOptionsMenu

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.general, container,  
    setHasOptionsMenu(true); // <-Add this line
    return view;
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    // If use specific menu
    menu.clear();
    inflater.inflate(R.menu.path_list_menu, menu);
    // If use specific menu

    ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("Your Fragment");
    super.onCreateOptionsMenu(menu, inflater);
}
于 2017-10-12T08:49:49.450 回答
1

如果您有一个包含许多片段的主要活动,通常使用navigationDrawer。你的片段有一系列标题,当你按下,让它们改变时,把它放在保存片段的主要活动中

@Override
     public void onBackPressed() {

    int T=getSupportFragmentManager().getBackStackEntryCount();
    if(T==1) { finish();}

    if(T>1) {
        int tr = Integer.parseInt(getSupportFragmentManager().getBackStackEntryAt(T-2).getName());
        setTitle(navMenuTitles[tr]);  super.onBackPressed();
      }

}

这假设你给每个片段一个标签,通常是在你将片段添加到navigationDrawer列表时的某个地方,根据在列表上按下的位置。所以那个位置就是我在标签上捕获的:

    fragmentManager.beginTransaction().
replace(R.id.frame_container, fragment).addToBackStack(position).commit();

现在,navMenuTitles 是您在 onCreate 上加载的内容

 // load slide menu items
        navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);

数组 xml 是 strings.xml 上的数组类型字符串资源

 <!-- Nav Drawer Menu Items -->
    <string-array name="nav_drawer_items">
        <item>Title one</item>
        <item>Title Two</item>
    </string-array>
于 2014-06-07T13:42:47.663 回答
1

将您的答案保存在 String[] 对象中,并在 MainActivity 中将其设置为 OnTabChange() 如下www

String[] object = {"Fragment1","Fragment2","Fragment3"};

public void OnTabChange(String tabId)
{
int pos =mTabHost.getCurrentTab();     //To get tab position
 actionbar.setTitle(object.get(pos));
}


//Setting in View Pager
public void onPageSelected(int arg0) {
    mTabHost.setCurrentTab(arg0);
actionbar.setTitle(object.get(pos));
}
于 2014-10-13T03:58:43.827 回答
1

你这样的铸造方法的缺点

((MainFragmentActivity) getActivity()).getSupportActionBar().setTitle(
        catTitle);

是您的片段在 MainActivityFragment 之外不再可重用。如果您不打算在该活动之外使用它,那么没有问题。更好的方法是根据活动有条件地设置标题。所以在你的片段中,你会写:

if (getActivity() instanceof ActionBarActivity) {
    ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle("Some Title");
}
于 2015-04-18T17:24:30.110 回答
1

如果您使用的是 google 提供的 android studio 1.4 稳定模板,那么您必须在方法中编写以下代码,onNavigationItemSelected在其中您的相关片段调用 if 条件。

 setTitle("YOUR FRAGMENT TITLE");
于 2015-10-19T11:06:09.067 回答
1

我得到了一个非常简单的解决方案,可以在片段或任何活动中设置 ActionBar Title,而不会让人头疼。

只需修改定义工具栏的xml,如下所示:

<android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimaryDark"
            app:popupTheme="@style/AppTheme.PopupOverlay" >

            <TextView
                style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
                android:id="@+id/toolbar_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/app_name"
                />
            </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout> 

1)如果要在片段中设置操作栏,则:

Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);

要在任何地方使用它,您可以在活动中定义一个方法

public void setActionBarTitle(String title) {
        toolbarTitle.setText(title);
    }

要在活动中调用此方法,只需调用它即可。

setActionBarTitle("Your Title")

要从活动片段调用此方法,只需调用它即可。

((MyActivity)getActivity()).setActionBarTitle("Your Title");
于 2018-08-23T09:52:33.550 回答
0

只是为了添加到选定的答案,您可能还想在您的主要活动中添加第二种方法。因此,您最终会在主要活动中使用以下方法:

public void setActionBarTitle(String title) {
    getSupportActionBar().setTitle(title);
}

public void setActionBarTitle(int resourceId) {
    setActionBarTitle(getResources().getString(resourceId);
}

这将允许您从 String 变量和资源 ID(例如R.id.this_is_a_stringstrings.xml 文件)设置标题。这也将更像是如何getSupportActionBar().setTitle()工作的,因为它允许您传递资源 ID。

于 2015-04-01T17:45:05.950 回答
0

如上所述,有很多方法。你也可以onNavigationDrawerSelected()在你的DrawerActivity

public void setTitle(final String title){
    ((TextView)findViewById(R.id.toolbar_title)).setText(title);
}

@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    fragment = null;
    String title = null;
    switch(position){

    case 0:
        fragment = new HomeFragment();
        title = "Home";
        break;
    case 1:
        fragment = new ProfileFragment();
        title = ("Find Work");
        break;
    ...
    }
    if (fragment != null){

        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager
        .beginTransaction()
        .replace(R.id.container,
                fragment).commit();

        //The key is this line
        if (title != null && findViewById(R.id.toolbar_title)!= null ) setTitle(title);
    }
}
于 2015-05-16T04:41:07.050 回答
0

至少对我来说,在运行时更改标签标题有一个简单的答案(经过大量挖掘):

TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.getTabAt(MyTabPos).setText("我的新文本");

于 2016-02-17T15:37:49.600 回答
0

如果您正在使用ViewPager(如我的情况),您可以使用:

getSupportActionBar().setTitle(YOURE_TAB_BAR.getTabAt(position).getText());

onPageSelected你的方法VIEW_PAGER.addOnPageChangeListener

于 2016-12-24T12:40:52.183 回答
0

在您的 MainActivity 中,在onCreate:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

在您的片段活动中onResume

getActivity().setTitle(R.string.app_name_science);

可选:- 如果它们显示空引用警告

Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);


Objects.requireNonNull(getActivity()).setTitle(R.string.app_name_science);
于 2019-06-01T13:17:49.600 回答
0

基于 Ashish 使用 Java 回答的解决方案

private void setUI(){
    mainToolbar = findViewById(R.id.mainToolbar);
    setSupportActionBar(mainToolbar);
    DrawerLayout drawer = findViewById(R.id.drawer_layout);
    NavigationView navigationView = findViewById(R.id.nav_view);
    mAppBarConfiguration = new AppBarConfiguration.Builder(
            R.id.nav_home, R.id.nav_messaging, R.id.nav_me)
            .setDrawerLayout(drawer)
            .build();

    navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    navController.addOnDestinationChangedListener(navDestinationChange);
    NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
    NavigationUI.setupWithNavController(navigationView, navController);
}

private NavController.OnDestinationChangedListener navDestinationChange = new NavController.OnDestinationChangedListener(){
    @Override
    public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
        if(R.id.nav_home==destination.getId()){
            destination.setLabel("News");
        }
    }
};
于 2021-01-19T19:54:15.940 回答