18

I have this code in my Activity:

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

I'm updating the ActionBar title from various fragments like this in onResume():

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

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

EDIT: 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() {
        @Override
        public void run() {
            Log.d("SWAPNIL", "IN RUN BEFORE: " + actionBar.getTitle());
            actionBar.setTitle(title);
            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!

Swapnil Bhoite
  • 392
  • 2
  • 12

7 Answers7

9

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();
}
Sufian
  • 6,405
  • 16
  • 66
  • 120
Swapnil Bhoite
  • 392
  • 2
  • 12
  • 2
    Unsure if I should say well done or thanks. This is a good lesson for every Android developer. Google should take these bugs seriously than just release more unfinished Android versions. – Sufian Oct 15 '15 at 13:41
  • Mark this as answer since it actually solves the problem. – Sufian Oct 15 '15 at 13:42
  • 1
    @Sufian thanks :) I'm surely gonna file this on Android bug reporting when I get some time to properly document the issue. – Swapnil Bhoite Oct 15 '15 at 15:05
  • where do you call this method? – Luke Allison Jun 13 '16 at 13:03
  • @LukeAllison I've a base Fragment from which all of my Fragments extend. I wrote above method in that base Fragment and call it inside other Fragments. So instead of calling `ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();` I'm calling `ActionBar actionBar = ((AppCompatActivity) getActivity(this)).getSupportActionBar();` from all the Fragments. – Swapnil Bhoite Jun 14 '16 at 13:11
  • the solution is more much simple: just use `getSupportActionBar().setTitle()`, on Kotlin it's `supportActionBar?.title = "NAME"` – user924 Jan 02 '21 at 11:13
6

You need to see the answer written by sorianiv here: In android app Toolbar.setTitle method has no effect – application name is shown as title

Adding the additional toolbar.setTitle("") resolved this issue for me.

    Toolbar toolbar = (Toolbar) root.findViewById(R.id.toolbar);
    toolbar.setTitle("");
        ((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
    toolbar.setTitle("Profiles");
Community
  • 1
  • 1
Luke Allison
  • 3,118
  • 3
  • 24
  • 40
  • the question you mentioned is bit different. I face the problem I posted because Android is returning me old `Activity` when I call `getActivity()` inside a `Fragment` (old Activity in the sense Activity gets recreated due to orientation change etc.). And hence my solution. – Swapnil Bhoite Jun 14 '16 at 13:17
  • Your solution is definitely more complete but I passed you this link as it solves the exact symptom you were having, that your toolbar was reverting to the app name after rotating. This solved the issue for me. If any more issues pop up due to the wrong activity being returned then I'll implement your solution. – Luke Allison Jun 15 '16 at 02:41
  • This solved a similar problem for me. I was calling `setTitle()` inside of the `onPostExecute()` of `AsyncTask`. It seems like you only need to call `setTitle("")` in `onCreate()` to make it possible to change the title further on with `getSupportActionBar().setTitle("...");` – archived Jul 03 '16 at 10:23
  • no need to call this method twice, just use `getSupportActionBar().setTitle()` once instead of referencing to toolbar view, p.s. on Kotlin it's `supportActionBar?.title = "NAME"` – user924 Jan 02 '21 at 11:02
2

I just ran into the same issue, and I solved it by using getSupportActionBar instead of toolbar.

getSupportActionBar().setTitle("...");
alekop
  • 2,838
  • 2
  • 29
  • 47
1

You're activity is getting recreated when you rotate the screen. So onCreate is getting called again, and you have not set a title there.

Add the following to your onCreate:

actionBar.setTile("Enter title here")
RED_
  • 2,997
  • 4
  • 40
  • 59
  • 1
    He is setting the title in `onResume()` of fragments. This will most likely not work. – Sufian Oct 13 '15 at 12:54
  • Yeah, Fragment's `onResume()` will get called after Activity's `onCreate()` – Swapnil Bhoite Oct 13 '15 at 13:12
  • Add some breakpoints and debug through and see what steps your app goes through after the rotation. Then you will know if your onResume() is being called and what is being called to change your actionbar title – RED_ Oct 13 '15 at 13:14
  • @RED_ from where I can debug, since it is the system who is changing title to app name. All I could do was to check if `onResume()` is called after Activity's `onCreate()` which is happening. – Swapnil Bhoite Oct 13 '15 at 13:27
  • @SwapnilBhoite add breakpoints in different methods of your fragment and activity and goto **Run -> Debug 'myApp'** (considering you are using Android Studio). If you find a solution, post it as answer so it helps someone in future. :) – Sufian Oct 14 '15 at 14:22
  • @Sufian I found the problem but no solution yet, I added logs in on`Create` of `Activity` and `onResume` of `Fragment`, turns out after rotation, when Activity gets recreated, `getActivity` from Fragment is returning old Activity (and so does old ActionBar)! Here's log:(I'm logging `Activity#toString`) – Swapnil Bhoite Oct 14 '15 at 16:33
  • `10-14 21:55:24.968 29718-29718/com.example.xxxxxxx D/SWAPNIL: onCreate: com.xxxxxxxxx.activities.ParentActivity@2b29230d 10-14 21:55:25.006 29718-29718/com.example.xxxxxxx D/SWAPNIL: onResume: com.xxxxxxxxx.activities.ParentActivity@2b29230d 10-14 21:55:32.400 29718-29718/com.example.xxxxxxx D/SWAPNIL: onCreate: com.xxxxxxxxx.activities.ParentActivity@2269072a 10-14 21:55:32.472 29718-29718/com.example.xxxxxxx D/SWAPNIL: onResume: com.xxxxxxxxx.activities.ParentActivity@2b29230d` – Swapnil Bhoite Oct 14 '15 at 16:33
  • I really don't know what to do now! – Swapnil Bhoite Oct 14 '15 at 16:34
0

maybe you can change your Action Bar / ToolBar, in onPostCreate() method in your Activity.. The code is just simple. I try to change my emulator / device orientation for many times and it works like charm..

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onPostCreate(savedInstanceState);
    toolbar.setTitle(mTitle);
}
0

I also met the problem as the title of the toolbar is set as empty ("") at the onCreateView, but after screen is rotated, then the the title bar shows application name not the empty string. This I also tried set empty string at the onResume, and finally it works! thanks

Kale
  • 1
-1

Add in Manifest file

<activity
     android:name=".Activity"
     android:configChanges="orientation|screenSize|keyboardHidden"/>

or code in onConfigChange()

if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){
    // Set Title for Landscape
 }else{
   // Set Title for Portrait
Nilesh Senta
  • 5,236
  • 2
  • 19
  • 27
  • 3
    Android [documentation](http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange) says, "This technique should be considered a last resort when you must avoid restarts due to a configuration change and is not recommended for most applications." I think this is not a proper solution, rather a hacky way. – Swapnil Bhoite Oct 13 '15 at 13:32
  • This configuration change is recommended far too often and is never the solution. Unless you want the exact same layout to remain after rotating do not use this. – Luke Allison Jun 13 '16 at 12:58