Swapnil Bhoite Swapnil Bhoite - 4 months ago 69x
Android Question

Toolbar (SupportActionBar) title changes to app name on orientation change

I have this code in my Activity:

protected void onCreate(Bundle savedInstanceState) {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {

I'm updating the ActionBar title from various fragments like this in

ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
if (actionBar != null) {

This is working fine, but after orientation change, the title changes to the app name again. How I can overcome this?

After investigating more, I tried this and found this weird behaviour:
Added this code where I was setting title in Fragments:

final ActionBar actionBar = ((AppCompatActivity)getActivity()).getSupportActionBar();
if (actionBar != null) {
new Handler().postDelayed(new Runnable() {
public void run() {
Log.d("SWAPNIL", "IN RUN BEFORE: " + actionBar.getTitle());
Log.d("SWAPNIL", "IN RUN AFTER : " + actionBar.getTitle());
}, 3000);

And here's the log:

10-13 10:27:04.526 3719-3719/com.example.xxxx D/SWAPNIL: onResumeHelp
10-13 10:27:07.528 3719-3719/com.example.xxxx D/SWAPNIL: IN RUN BEFORE: MY APP NAME
10-13 10:27:07.528 3719-3719/com.example.xxxx D/SWAPNIL: IN RUN AFTER : title
10-13 10:27:21.012 3719-3719/com.example.xxxx D/SWAPNIL: onResumeHelp
10-13 10:27:24.013 3719-3719/com.example.xxxx D/SWAPNIL: IN RUN BEFORE: title
10-13 10:27:24.013 3719-3719/com.example.xxxx D/SWAPNIL: IN RUN AFTER : title

It was getting changed as per logs but wasn't reflected in UI.
Please help me!


Okay, finally, after spending 2 days on this silly thing, I got the solution (I would say workaround).

This is probably a nested Fragment bug.

I have nested Fragment structure. As we know Fragment.getActivity() returns parent Activity. After lot of debugging I observed that if you call getActivity() after orientation change (even inside Fragment.onActivityCreated()) it returns reference of the old Activity except in top most parent fragment where it correctly returns the newly created Activity.

So I've written this method to get current Activity from any Fragment:

 * When inside a nested fragment and Activity gets recreated due to reasons like orientation
 * change, {@link android.support.v4.app.Fragment#getActivity()} returns old Activity but the top
 * level parent fragment's {@link android.support.v4.app.Fragment#getActivity()} returns current,
 * recreated Activity. Hence use this method in nested fragments instead of
 * android.support.v4.app.Fragment#getActivity()
 * @param fragment
 *  The current nested Fragment
 * @return current Activity that fragment is hosted in
public Activity getActivity(Fragment fragment) {
    if (fragment == null) {
        return null;
    while (fragment.getParentFragment() != null) {
        fragment = fragment.getParentFragment();
    return fragment.getActivity();