Setting Custom ActionBar Title from Fragment

JavaAndroidAndroid FragmentsAndroid ActionbarAndroid Fragmentactivity

Java Problem Overview


In my Main FragmentActivity, I setup my custom ActionBar title like this:

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

This works perfect. However, once I open other Fragments, I want the title to change. I am not sure how to access the Main Activity to do this? In the past, I did this:

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

Can someone advise on the proper method?

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>

Java Solutions


Solution 1 - Java

What you're doing is correct. Fragments don't have access to the ActionBar APIs, so you have to call getActivity. Unless your Fragment is a static inner class, in which case you should create a WeakReference to the parent and call Activity.getActionBar from there.

To set the title for your ActionBar, while using a custom layout, in your Fragment you'll need to call getActivity().setTitle(YOUR_TITLE).

The reason you call setTitle is because you're calling getTitle as the title of your ActionBar. getTitle returns the title for that Activity.

If you don't want to get call getTitle, then you'll need to create a public method that sets the text of your TextView in the Activity that hosts the Fragment.

In your Activity:

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

In your Fragment:

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

Docs:

Activity.getTitle

Activity.setTitle

Also, you don't need to call this.whatever in the code you provided, just a tip.

Solution 2 - Java

===Update October, 30, 2019===

Since we have new components such as ViewModel and LiveData, we can have a different/easier way to update Activity Title from Fragment by using ViewModel and Live Data

Activity

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
    })
} }

MainFragment

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")
} }

And MainModelView:

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

And then you can update the Activity title from Fragment using viewModel.updateActionBarTitle("Custom Title From Fragment")

===Update April, 10, 2015===

You should use listener to update your action bar title

Fragment:

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

And Activity:

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

Read more here: https://developer.android.com/training/basics/fragments/communicating.html

Solution 3 - Java

Google examples tend to use this within the fragments.

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

The fragment will belong to an ActionBarActivity and that is where the reference to the actionbar is. This is cleaner because the fragment doesn't need to know exactly what activity it is, it only needs to belong to an activity that implements ActionBarActivity. This makes the fragment more flexible and can be added to multiple activities like they are meant to.

Now, all you need to do in the fragment is.

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

This works well if you have a base fragment that your fragments inherit from instead of the normal fragment class.

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

Then in your fragment.

public class YourFragment extends BaseFragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getActionBar().setTitle("Your Title");
    }
}

Solution 4 - Java

I don't think that the accepted answer is a perfect answer for it. Since all the activities that use

> Toolbar

are extended using

> AppCompatActivity

, the fragments called from it can use the below mentioned code for changing the title.

((AppCompatActivity) context).getSupportActionBar().setTitle("Your Title");

Solution 5 - Java

Setting Activity’s title from a Fragment messes up responsibility levels. Fragment is contained within an Activity, so this is the Activity, which should set its own title according to the type of the Fragment for example.

Suppose you have an interface:

interface TopLevelFragment
{
    String getTitle();
}

The Fragments which can influence the Activity’s title then implement this interface. While in the hosting activity you write:

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

In this manner Activity is always in control what title to use, even if several TopLevelFragments are combined, which is quite possible on a tablet.

Solution 6 - Java

A simple Kotlin example

Adapt this to your fragment classes:

    /**
     * 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!"
        }


    }

Solution 7 - Java

In the Fragment we can use like this, It's working fine for me.

getActivity().getActionBar().setTitle("YOUR TITLE");

Solution 8 - Java

Just in case if you are having issues with the code, try putting getSupportActionBar().setTitle(title) inside onResume() of your fragment instead of onCreateView(...) i.e

In MainActivity.java :

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

In Fragment:

 @Override
 public void onResume(){
     super.onResume();
     ((MainActivity) getActivity()).setActionBarTitle("Your Title");
 }

Solution 9 - Java

Use the following:

getActivity().setTitle("YOUR_TITLE");

Solution 10 - Java

Here is my solution for setting the ActionBar title from fragments, when using NavigationDrawer. This solution uses an Interface so the fragments does not need to reference the parent Activity directly:

  1. Create an Interface:

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

  2. In the Fragment's onAttach, cast the activity to the Interface type and call the SetActivityTitle method:

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

  3. In the activity, implement the ActionBarTitleSetter interface:

    @Override public void setTitle(String title) { mTitle = title; }

Solution 11 - Java

Best event for change title 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);
}

Solution 12 - Java

If you have a main activity with many fragments you put in, usually using the navigationDrawer. And you have an array of titles for yours fragments, when you press back, for them to change, put this in the main actity that hold the fragments

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

}

This assumes that for each fragment you give it a tag, usually somewhere when you add the fragments to the list of navigationDrawer, according to the position pressed on the list. So that position is what i capture on the tag:

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

Now, the navMenuTitles is something you load on the onCreate

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

The array xml is an array type string resource on strings.xml

 <!-- Nav Drawer Menu Items -->
    <string-array name="nav_drawer_items">
        <item>Title one</item>
        <item>Title Two</item>
    </string-array>

Solution 13 - Java

Save ur Answer in String[] object and set it OnTabChange() in MainActivity as Belowwww

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

Solution 14 - Java

The downside to your approach of casting like so

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

is that your fragment is no longer reusable outside of MainActivityFragment. If you don't plan to use it outside of that activity, then there's no problem. A better approach would be conditionally set the title depending on the activity. So inside your fragment, you would write:

if (getActivity() instanceof ActionBarActivity) {
    ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle("Some Title");
}

Solution 15 - Java

if you are using android studio 1.4 stable template provided by google than simple you had to write following code in onNavigationItemSelected methode in which your related fragment calling if condition.

 setTitle("YOUR FRAGMENT TITLE");

       

  

Solution 16 - Java

> I am getting a very simple solution to set ActionBar Title in either > fragment or any activity without any headache. > > Just modify the xml where is defined Toolbar as below :

<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) If you want to set the actionbar in a fragment then :

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

> For using it from anywhere, you can define a method in the activity

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

> To call this method in activity, simply call it.

setActionBarTitle("Your Title")

> To call this method from fragment of the activity, simply call it.

((MyActivity)getActivity()).setActionBarTitle("Your Title");

Solution 17 - Java

Just to add onto the selected answer, you may also want to add a second method to your main activity. So you would end up with the following methods in your main activity:

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

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

This will allow you set the title from both a String variable as well as a resource ID such as R.id.this_is_a_string from your strings.xml file. This will also work a little more like how getSupportActionBar().setTitle() works since it allows you to pass in a resource ID.

Solution 18 - Java

There are many ways as as outlined above. You can also do this in onNavigationDrawerSelected()in your 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);
	}
}

Solution 19 - Java

At least for me, there was an easy answer (after much digging around) to changing a tab title at runtime:

TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.getTabAt(MyTabPos).setText("My New Text");

Solution 20 - Java

If you're using ViewPager (like my case) you can use:

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

in onPageSelected method of your VIEW_PAGER.addOnPageChangeListener

Solution 21 - Java

In your MainActivity, under onCreate:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

And in your fragment activity under onResume:

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

Optional:- if they show warning of null reference

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


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

  

Solution 22 - Java

Solution based on Ashish answer with 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");
        }
    }
};

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTheLettuceMasterView Question on Stackoverflow
Solution 1 - JavaadnealView Answer on Stackoverflow
Solution 2 - JavaFrank NguyenView Answer on Stackoverflow
Solution 3 - JavaKalel WadeView Answer on Stackoverflow
Solution 4 - JavaManoj PerumarathView Answer on Stackoverflow
Solution 5 - JavaAleks N.View Answer on Stackoverflow
Solution 6 - Javalasec0203View Answer on Stackoverflow
Solution 7 - JavaNagarjunaReddyView Answer on Stackoverflow
Solution 8 - JavarealpacView Answer on Stackoverflow
Solution 9 - JavaAnisetti NagendraView Answer on Stackoverflow
Solution 10 - JavaAssaf S.View Answer on Stackoverflow
Solution 11 - JavaAhmad AghazadehView Answer on Stackoverflow
Solution 12 - JavaMiguelView Answer on Stackoverflow
Solution 13 - JavaNarendra KumarView Answer on Stackoverflow
Solution 14 - JavaMieczysław Daniel DybaView Answer on Stackoverflow
Solution 15 - JavaManan PatelView Answer on Stackoverflow
Solution 16 - JavaRamapati MauryaView Answer on Stackoverflow
Solution 17 - JavaCodyEngelView Answer on Stackoverflow
Solution 18 - JavatricknologyView Answer on Stackoverflow
Solution 19 - JavaMarkView Answer on Stackoverflow
Solution 20 - JavaRezaView Answer on Stackoverflow
Solution 21 - JavaAmit SinghView Answer on Stackoverflow
Solution 22 - JavatsiftisView Answer on Stackoverflow