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!
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();
}
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");
I just ran into the same issue, and I solved it by using getSupportActionBar instead of toolbar.
getSupportActionBar().setTitle("...");
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")
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);
}
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
Related
I have a Navigation Drawer in the main activity of my app. On the onCreate method of the activity I initialize one of the fragments like this :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
MenuItem menuItem = navigationView.getMenu().findItem(R.id.menu_history);
openFragment(menuItem);
}
public void openFragment(MenuItem menuItem){
Fragment newFragment = null;
switch (menuItem.getItemId()){
case R.id.menu_history :
newFragment = new HistoryFragment();
break;
//.....
}
if (newFragment != null){
//Replace content frame in activity_main.xml with newFragment
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, newFragment)
.commit();
menuItem.setChecked(true);
getSupportActionBar().setTitle(menuItem.getTitle());
}
drawerLayout.closeDrawers();
}
This all works well, the fragment appears on startup with the title on the toolbar being "History". But when the app goes into onPause and then onResume the toolbar title switches from "History" to the app name. I suspect this is an issue with onResume not opening the fragment / returning to its previous state correctly, because when I added the following lines to onResume the issue stopped:
#Override
protected void onResume() {
super.onResume();
MenuItem menuItem = navigationView.getMenu().findItem(R.id.menu_history);
openFragment(menuItem);
}
That solution seems to fix it but that means it has to reload the fragment with the animations every time the app is resumed, which isn't optimal. Any ideas on how to fix this?
If it helps, to recreate the issue I found useful to make the app split screen, because it always calls onResume. Thanks.
Inside your openFragment() method, you write:
getSupportActionBar().setTitle(menuItem.getTitle());
This is the only thing that changes your toolbar's title.
Note that this code has nothing to do with your Fragments, per se. When your activity is destroyed and recreated, the active Fragment will be successfully (automatically) destroyed and recreated by the FragmentManager... but your openFragment() method won't run again and so nothing will update your toolbar's title.
There are numerous ways you could solve this. Probably the right thing to do is update your toolbar's title from within one of your Fragment's lifecycle methods.
Edit: A reasonable place to update your toolbar's title would be in your fragment's onActivityCreated() method. This will run both when the fragment is first added and during recreation. Something like:
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("hello world");
}
If you do not want to re-create the fragment each time, you should use saveInstanceState like mentioned here: https://stackoverflow.com/a/17135346/1505074
I have a generic
MyActivity extends AppCompatActivity
I don't override the toolbar with a custom xml defined toolbar, just use the generated one Android provides.
I can set the title via your normal
getSupportActionBar().setTitle("foo");
but setting the subtitle via
getSupportActionBar().setSubtitle("bar");
doesn't set it. It remains blank. I'm doing this onCreate()
(I feel I've done this many times before with no fail)
Although I've noticed if I visit another activity, then return, the subtitle would then show... not on orientation change, not on recreate() but only when I'm returning from an activity.
I'm experiencing this on 5.0 and 7.0
For the time being I'll likely define my own Toolbar and move forward since that seems where most people have solutions for this same problem.
Relevant code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_replenishment_list);
ButterKnife.bind(this);
MyApplication.getInstance().getComponent().inject(this);
setupUI();
}
private void setupUI() {
setupActionBar();
}
private void setupActionBar() {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
//TODO: not working unless activity is recreated...
// explore custom xml defined toolbar
//actionBar.setTitle("different title than what is defined in manifest"); <-- this does work, but not this
actionBar.setSubtitle(UserUtil.getFormattedFirstNameLastName(userService.getUserFromJWT(), this));
}
}
I have put the below code in my onCreate() method.
ActionBar actionBar = getActionBar();
if (actionBar==null) {
System.out.println("TEST NULL");
} else {
System.out.println("TEST NOT NULL");
}
The result is null. When I add the toolbar first it works fine.
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getActionBar();
actionBar.setSubtitle("TESTING");
Your getSupportActionBar or getActionBar will return null if you didn't set toolbar to it. You need to set the toolbar to your action bar before using getSupportActionBar or getActionBar.
I'm trying to change the title of activity, where i'm going to the activity from the fragments, so when i click on the hardware back button the title doesn't chnage to the one that i have provided in that activity i.e
this.setTitle("Something");
I have also tried
setTitle("Something");
Update
When i use the below mentioned code i run into a problem where the title that i assign in the mainActivity stay in all the pages, hence in the frgament getActivity().setTitle(""); seems to be useless in this case, so instead of changing everywhere the title using the below mentioned code i.e changing the actionbar title using getsupportactionbar.settitle(""), is there an easy way to do.
By any means can i know if an activity has came from the system back button back state or not?
You can handle this situation with onResume() method
//...
#Override
onResume(){
super.onResume();
this.getActionBar().setTitle("Something");
}
ı think, that will help you.
Try this:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ActionBar ab = getActionBar();
ab.setTitle("My Title");
ab.setSubtitle("sub-title");
}
EDIT:
For SupportActionBar use:
ActionBar actionBar = getSupportActionBar();
EDIT2:
I use this to set Title from every fragment
#Override
public void onResume() {
super.onResume();
// Set the title
getActivity().getActionBar() //getSupportActionBar()
.setTitle(R.string.fragment_title);
}
If you always add your fragment to backstack when changing, then backpress can be override as follows to always get your previous fragment's title:
#Override
public void onBackPressed() {
int T= getFragmentManager().getBackStackEntryCount();
if (getFragmentManager().getBackStackEntryCount() == 0) {
finish();
}
else if (getFragmentManager().getBackStackEntryCount() == 1) {
finish();
}
else {
String tr = getFragmentManager().getBackStackEntryAt(T-2).getName();
setTitle(tr);
getFragmentManager().popBackStack();
}
}
If you are occured this in Kotlin just remove Label from destination in Your navigation graph.
getSupportActionbar().setTitle("Your Title")
You have to call this whenever you want to change your title.
If you are switching between fragments call the method again and switch it back to your old title.
I want to change ActionBar home button left padding. I've tried this solution. But when I try findViewById(android.R.id.home) I get null. In the same time android.R.id.home is not 0.
And this happens only if I use android-suppot-v7. If I don't use support library all goes good.
Maybe someone can help me?
Here is my simple code:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getSupportActionBar();
actionBar.setHomeButtonEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowHomeEnabled(true);
ImageView view = (ImageView)findViewById(android.R.id.home);
if (view !=null){
view.setPadding(10, 0, 0, 0);
}
}
}
Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.timoshkois.actionbar.MainActivity">
</RelativeLayout>
Hmm you're not wrong, if you look at the source for the Activity you inherit from, they also use android.R.id.home
https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/v7/appcompat/src/android/support/v7/app/ActionBarActivity.java
Like this
#Override
public final boolean onMenuItemSelected(int featureId, android.view.MenuItem item) {
if (super.onMenuItemSelected(featureId, item)) {
return true;
}
final ActionBar ab = getSupportActionBar();
if (item.getItemId() == android.R.id.home && ab != null &&
(ab.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
return onSupportNavigateUp();
}
return false;
}
Looking how the ActionBar is created it uses these classes:
https://github.com/android/platform_frameworks_support/blob/5476e7f4203acde2b2abbee4e9ffebeb94bcf040/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java
https://github.com/android/platform_frameworks_base/blob/master/core/java/com/android/internal/app/WindowDecorActionBar.java
which leads to the ActionBar class, this has a possible clue about why it returns null
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/ActionBar.java#L106
/**
* Standard navigation mode. Consists of either a logo or icon
* and title text with an optional subtitle. Clicking any of these elements
* will dispatch onOptionsItemSelected to the host Activity with
* a MenuItem with item ID android.R.id.home.
*
* #deprecated Action bar navigation modes are deprecated and not supported by inline
* toolbar action bars. Consider using other
* <a href="http://developer.android.com/design/patterns/navigation.html">common
* navigation patterns</a> instead.
This deprecation means the new ToolBar won't use nav modes so maybe this also means Toolbar will not have this Android id (R.id.home) - which makes sense as the previous links show that app compat not uses a Toolbar under the hood, which legacy implementations will not be using.
As a test you could do what the comment says and override onOptionsItemSelected press the logo and query the view you are passed to find it's id getId()
Apparently, 'home' is the name of your layout file? [No, I see that's activity_main.] To access the relativelayout item, it needs an ID of its own, like android:id="#+id/home"
Hi there I have been using the ViewPagerIndicator library for some time now and I want my action-bar's title to change every time the user swipes to another Fragment to the other pages here is the code I am thinking off but it is just not working.
Activity miz = getActivity();
miz.setTitle("Miz");
I have put this code in all my Fragments displaying different titles every time but for some reason it is not working properly as it is always late. I think it may have something to do with the OnCreate , OnResume or OnPause and can not lay a finger on it can some one help ? I want the Title of the Action Bar to change while the next Fragment is visible to the user.
I have also though of some code like this
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
Activity miz = getActivity();
miz.setTitle("Miz");
}
Regular :
this.getActivity().getActionBar().setTitle(title);
With ActioBarSherlock :
this.getSherlockActivity().getSupportActionBar().setTitle(title);
You can do this:
ActionBar actionBar = getActionBar(); // or getSupportActionBar() for ActionBarSherlock
actionBar.setTitle("test");
In a Fragment:
ActionBar actionBar = getActivity().getActionBar();
actionBar.setTitle("test");
Try
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("Miz");
It will work
Reference: Setting a subtitle on my Toolbar from a fragment