I have an ActionBar in my Android app (API Level 14).
There is a home button with my app icon. In MainActivity I write a short Text in an EditText View.
When I navigate to PreferenceActivity the icon gets an arrow to signal me, I can navigate to home Activity (MainActivity).
// PreferenceActivity-onCreate
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
I click on that app icon in ActionBar to return to MainActivity
// PreferenceActivity
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.home:
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Now my MainActivity was created again und the text in EditText is gone.
I thought I can keep alive the MainActivity with die Intent.FLAG_ACTIVITY_CLEAR_TOP.
I want to have a behaviour like i use my return button on device.
If you want to return to an existing instance of MainActivity, you need to do this:
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Using CLEAR_TOP alone causes a new instance of MainActivity to be created.
I believe this is the correct way of doing this. https://stackoverflow.com/a/15933890/238768
Using Intent.FLAG_ACTIVITY_CLEAR_TOP will cause the exact opposite behaviour of what Gepro wants to do!
Related
I got SettingActivity from AndroidStudio Gallery, which uses ActionBar. Everything is fine when I click back button from ActionBar inside SettingsActivity. But when I want to return to main activity using this button in ActionBar nothing happens.
My SettingsActivity uses headers for preferences, so I thought I can check whether I am "inside" any of these headers, and if answer is none then I am in main setting screen and I can call main activity using startActivity(this,MainActivity.class). But problem is I cann't determine whether I am in start screen or in some header. Of course if there are more easy ways to do it I would appreciate it very much.
to make action bar back press return back , you have to do it in menu item selected
#Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case android.R.id.home:
Intent homeIntent = new Intent(this, HomeActivity.class);
homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(homeIntent);
}
return (super.onOptionsItemSelected(menuItem));
}
I'm developing some application and I have one problem.
I have :
1. Activity A (Navigation Drawer pattern) with ListFragment in FrameLayout:
xml:
<FrameLayout
...>
</FrameLayout>
<LinearLayout
...>
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
Activity B which shows the detail data of ListView in ListFragment.
How can I go back (using Navigation Up Button) from activity B to Activity A with saving UI of the ListFragment (Activity re-creates if I go back using Home Back).
Btw, if I press the back button on my phone, activity does not re-create and returns in previous state.
When you use UP navigation, then the previous activity is recreated. To prevent that from happening while you preserve the UP navigation, you can get the intent of the parent activity, and bring it to front if it exists, otherwise create it if not.
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent parentIntent = NavUtils.getParentActivityIntent(this);
parentIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(parentIntent);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
I also specified launchMode="singleTop" in the Manifest. but I am not sure if that was necessary.
One thing you can do to prevent the first activity to recreate is by just calling finish() on the second activity when that back button is pressed.
Not tested, but I believe the id is android.R.id.home, so all you have to do is override onOptionsItemSelected in the second activity, like this:
/**
* Handles the selection of a MenuItem.
*/
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
In my activity which extends SherlockFragmentActivity I have action bar and have also set actionBar.setDisplayHomeAsUpEnabled(true) to come back to my previous activity. Everything works fine. But when i click on home button, the background color should be applied only to the app icon but it also applies to the "title" on action bar as shown in screen shot. I dont want this to happen. When i click on home button, only the app icon should be click able(background color should be applied only for app icon) and not the title. Any idea how can i do this?
my activity code:
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(some_string);
Don't forget this part, because that home button is also a MENU button.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// This is called when the Home (Up) button is pressed in the action bar.
// Create a simple intent that starts the hierarchical parent activity and
// use NavUtils in the Support Package to ensure proper handling of Up.
Intent upIntent = new Intent(this, MainActivity.class);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
// This activity is not part of the application's task, so create a new task
// with a synthesized back stack.
TaskStackBuilder.from(this)
// If there are ancestor activities, they should be added here.
.addNextIntent(upIntent)
.startActivities();
finish();
} else {
// This activity is part of the application's task, so simply
// navigate up to the hierarchical parent activity.
NavUtils.navigateUpTo(this, upIntent);
}
return true;
}
return super.onOptionsItemSelected(item);
}
The standard Android UI pattern is to include the title in the pressed state.
However, I think if you followed this link (describing how to add a custom view to the left of an actionbar) How to align items in action bar to the left? , and set the title to empty. The below code worked on my local device
ActionBar action=getActionBar();
action.setDisplayShowCustomEnabled(true);
action.setHomeButtonEnabled(true);
action.setDisplayShowTitleEnabled(false);
TextView title =new TextView(getApplicationContext());
title.setText("Your Title here");
title.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
action.setCustomView(title);
From my observation from Gmail and TED app the behavior of up navigation it will navigate to parent with the same state (scroll position) not like what Google say in their doc Implement Up Navigation which like create a parent intent and start it.
I implement the code from Android sample code and all state are gone (All Extra parameters I have previously set and scroll position). What is the proper way on this ? I can't find any on Android document.
Below is the code:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent upIntent = new Intent(this, MyParentActivity.class);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
// This activity is not part of the application's task, so create a new task
// with a synthesized back stack.
TaskStackBuilder.from(this)
.addNextIntent(new Intent(this, MyGreatGrandParentActivity.class))
.addNextIntent(new Intent(this, MyGrandParentActivity.class))
.addNextIntent(upIntent)
.startActivities();
finish();
} else {
// This activity is part of the application's task, so simply
// navigate up to the hierarchical parent activity.
NavUtils.navigateUpTo(this, upIntent);
}
return true;
}
return super.onOptionsItemSelected(item);
}
In my case I got 3 activities say A B and C, when user navigate from A to B I put some extras and onCreate of B I use that extras to query data from database to populate my rows and when I navigate back from C all extras are gone and Activity B show nothing.
The "standard" behaviour for an android activity is, that a new instance of the activity is created, every time there is a new intent for this activity (see launchMode-docu here). Because of this your extras seem to be gone, if you call navigateUpTo.
In your case, I would advise to use
android:launchMode="singleTop"
for your parent activity in your AndroidManifest.xml. This way you will return to your existing activity (as long as it is on the top of the back stack of your task). This way your extras will be preserved.
I too, do not understand why this is not mentioned in the Google doc you cite, as this seems the behaviour one expects if using up-navigation.
This is an alternative solution to the accepted answer:
If you cannot change the launchMode of your activity or if the parent activity is not on top of the back stack (e.g. A is parent of C), you cannot use the solution above. In this case you have to extend your navigateUpTo call to tell the activity, that it should not be recreated, if it is on the back stack:
Intent intent = NavUtils.getParentActivityIntent(this);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
NavUtils.navigateUpTo(this, intent);
I had a similar issue when I called startActivityForResult() in my main activity with fragments and then tried to return to it from the callee using Up navigation.
Solved by implementing Up navigation as:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
setResult(RESULT_CANCELED);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
In this case Up button behaves like an ordinary Back button and all states are preserved.
you can use this :
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
super.onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
You would need to save the state on the parent activity and recover it after returning from the calling one.
See Saving Android Activity state using Save Instance State for a complete explanation of the preocess, with code.
I'm using the Actionbar and it's "up" button to return from a detail activity to the main activity, which works fine. Similarly, the user can press the system "back" button to return to the main activity.
In my main activity, in onCreate() data is downloaded from the internet to display upon app start. I noticed that when I use the Actionbar "up" button to go from detail to main activity, onCreate() is run, re-downloading the data. But onCreate() is not run when I use the system "back" button, therefore immediately showing the main activity view.
The code I use in the detail activity to implement the "up" button is:
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
I would like the "up" button to behave like the "back" button and not rerun onCreate(). But I'm unsure how to make this happen, or which code path the "back" button implements to return to the main activity.
Thanks!
Instead of starting a whole new activity simply finish the details activity you are in
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
Then you will return to the previous activity on the activity stack (your main activity) and onCreate shouldn't be called
If you want Up to do exactly what Back does, you can do this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
Note that the default implementation of onBackPressed() just calls finish(), but onBackPressed can be overridden.
I think a better solution can be found in this post.
Calling finish() works in specific situations but may not always produce the behavior described in the documentation e.g:
By calling
Intent intent = NavUtils.getParentActivityIntent(this);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
NavUtils.navigateUpTo(this, intent);
you'll return to the parent activity in the state in which you left it. If you have a flat app structure, it'll still act just like the Back button.
for a real "home" functionality , you should see the api demos ,under "App/Activity/Reorder Activities" .
the reason : what if you have something like this : activity1->activity2->activity3 , and now you wish to go to activity1 by pressing the home button on the action bar?
I believe the simplest way is to override the "getParentActivityIntent" method of the detail activity adding the flag "Intent.FLAG_ACTIVITY_CLEAR_TOP":
#Nullable
#Override
public Intent getParentActivityIntent() {
Intent intent = super.getParentActivityIntent();
if (intent != null) {
return super.getParentActivityIntent().addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
return intent;
}
There is another solution which can be in hand for somebody. I had the same double-behavior when user pressed Back and ActionbarBack buttons. I was fine with Back btn behaviour. I didn't want an activity to be recreated. So I overrode the method
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
Works fine for me