I'm having some problems with navigation and the up button of the activity. I have two tabs implemented with Viewpager in one activity and then another activity which is loaded from the previous one. When the user clicks the phone's back button or the activity's up button, I want to go back to the previously selected tab and fragment of the first activity.
So far I've been able to do it for the back button, with onSaveInstanceState and the following code:
#Override
protected void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putInt("currentPage", mViewPager.getCurrentItem());
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
int page = savedInstanceState.getInt("currentPage", 0);
mViewPager.setCurrentItem(page);
getSupportActionBar().setSelectedNavigationItem(page);
}
}
Why is this not working for the up button? What do I have to do?
Any help is appreciated and sorry if this is an issue easy to solve, but I'm rather new to the Android programming.
I finally found the solution at Returning from an activity using navigateUpFromSameTask(). savedInstanceState was null when the activity was recreated. To avoid so, the launch mode of the activity has to be declared as singleTop in the Android manifest.
Related
I have two Activities A and B.
Activity A has a Tablayout with some Tabs. When I navigate from A to B I use this:
Intent intent = new Intent(A, B.class);
A.startActivity(intent);
When I now navigate back from B to A I have a question:
1) When using Android's back button, the selected tab / scrolling position from A was remembered
2) When using an Intent or NavUtils.navigateUpFromSameTask(this); then the selected tab and scroll Position is NOT remembered but set to initial value
Can someone explain me what is going on here?
1) when navigation from activity A to B, the android system does not destroy activity A, but takes it to the back stack and adds B to the foreground. thats why when you press the back button or call onBackPressed() from the java code activity B is destroyed and A is set to the foreground. here is an example from the docs : Understand Tasks and Back stack
2) when using an intent/navigateUpFromSameTask activity A is recreated and set to the foreground and B is set to the background, it's like adding another activity A to the stack so it will be A,B,A but if you press the back btn then you will be back to B and then A.
if you want to keep the scroll position and other data in activity A you call the onBackPressed in B or use the onSaveInstanceState to save the data and use it in the onCreate .
here is an example of saved instance:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("VariableName", variableData);
savedInstanceState.putString("VariableName", variableData);
savedInstanceState.putString("VariableName", variableData);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.penguin_main);
if(savedInstanceState!=null){
bookData = (String) savedInstanceState.getSerializable("VariableName");
bookData = (String) savedInstanceState.getSerializable("VariableName");
bookData = (String) savedInstanceState.getSerializable("VariableName");
}
}
You can set the current scroll position and tab position in activity A's on overriding onSaveInstance(Bundle savedInstanceState) method. When return to activity you can get onRestoreInstanceState(Bundle savedInstanceState) to restore it.
Hope it helps :)
Because NavUtils.navigateUpFromSameTask() just calls startActivity() and if android:launchMode="standard" the activity will be instantiated and created again and that is why can not remember the previous selected tab. To solve this issue you can override onNavigateUp() and inside that setCurrentItem(index) the index of tab you want to be displayed.
#Override
public boolean onNavigateUp() {
myViewPager.setCurrentItem(position, true);
return true;
}
Edit
You can use another solution to solve the problem by setting android:launchMode="singleTop" on activity but this solution may not applicable in all the application.
When you start an Activity, the first page will be opened! But when the back button is pressed, it navigates between the saved state of the activityTo simulate the back button pressed, you can try this:
#Override
public void onBackPressed() {
finish(); //your choice, thought not needed as super.onBackPressed(); is called if nothing is assigned here
}
or on toolbar back button clicked click:
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
I have two Fragments in my ViewPager as Tabs. These share a toolbar. You get to the SettingsActivity by clicking an Icon on the toolbar.
So you can access the SettingsActivity while either Fragment A is the visible one, or Fragment B is the visible one.
When I navigate back from the SettingsActivity to the fragments, by clicking the Up Button in the toolbar (actionBar.setDisplayHomeAsUpEnabled(true);), I want to have the fragment visible, that I had visible when I accessed SettingsActivity.
Without any special code (= current state) it seems to always return to the first Fragment in the ViewPager (i.e. the most left one).
Parent Activity for the Up Navigation is MainActivity, where I have the ViewPager with the 2 Fragments as Tabs.
Use the state saving callback to save the state of your MainActivity:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("SELETED_TAB_INDEX", mSelectedTabIndex);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) { // so the activity is being restarted
pager.setCurrentItem(savedInstanceState.getInt("SELETED_TAB_INDEX"));
}
}
save your fragment to backstack. This way, back button for fragments would work same as it runs for activities.
Here: http://developer.android.com/training/implementing-navigation/temporal.html
I am new to fragments and have a lot of problems understanding and working with them. I will try to describe my problem step by step:
I start with a list
after selecting an item i start an activity with a dynamic url in a webview
If portrait, only the webview is showed, if landscape the list is presented next to it
In landscape when i select another item, it is showd in the webview (check the code)
Problem: When i turn back now to portrait the first selected item is showd instead of the last one.
How can i update the activity so it will keep the last opened url after orientation change?
if (fragment==null || ! fragment.isInLayout()) {
Intent intent = new Intent(this.getActivity(), DetailViewActivity.class);
intent.putExtra("link", urlforwebview);
startActivity(intent);
} else {
DetailView detailFragment =
(DetailView)
getFragmentManager().findFragmentById(R.id.detailfragment);
detailFragment.changeWebviewURL(urlforwebview);
}
FIX:
Added this to my detailfragment:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("currentUrl", url);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
// Restore last state for checked position.
url = savedInstanceState.getString("currentUrl", "");
changeWebviewURL(url);
}
}
Have a look at : onSaveInstanceState.
http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
This answer here can help you: android fragment- How to save states of views in a fragment when another fragment is pushed on top of it
In my application i have a FragmentPager. Now each Fragment has a next button with which i navigate to the next fragment. Via the next button i know that the user is navigation away from the view. But how do i know if the user has clicked on the tabs. Will the
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_CONTENT, mContent);
}
function be called when a user presses a different tab ? Can i save the state and restore it on the
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ((savedInstanceState != null)
&& savedInstanceState.containsKey(KEY_CONTENT)) {
mContent = savedInstanceState.getString(KEY_CONTENT);
}
}
will this work ? What other way can i know that the user has clicked on the different tab ?
Kind Regards
First of all, are you using ActionBarSherlock for you actionbar/tabs? I recommend that you do since you'll get a cross-version way of working with the actionbar.
In any case, you should add a listener to each tab before adding it to the actionbar. With the listener implemented you know when a tab has been selected, reselected and unselected
I'm not sure about when the onSaveInstanceState is called (try it using the debugger!), but with the listener implemented you'll get a fool-proof way of knowing what goes on with your tabs.
I have 3 tabs in my sample application with activity group. First tab contains search activity i.e.Home/Root activity and am displaying the results of search in another activity but under same tab i.e Tab1. When I press back button in result activity, it is going to search activity. Everything works fine till here. Now I want to go search activity by pressing tab1 instead of pressing back button. How can achieve this? I tried something like this
public class TabSample extends TabActivity {
public TabHost tabHost;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.tabHost = getTabHost();
tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("OPT")
.setContent(new Intent(this, TabGroup1Activity.class)));
tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("EDIT")
.setContent(new Intent(this, TabGroup2Activity.class)));
tabHost.setCurrentTab(1);
tabHost.setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String arg0) {
if (tabHost.getCurrentTabTag().equals("tab1")) {
//What should I do to display search activity here
} else {
tabHost.setCurrentTab(1);
}
}
});
tabHost.setFocusable(true);
tabHost.requestFocus();
}
}
Can anyone please help let me know how to invoke search activity when tab is pressed? What will go into if part? Because if I use tabHost.setCurrentTab(index), it will display result activity but not search activity.
NOTE: I followed the tutorial given in this link.
I think what you want to do is this: when the 'tab1' tag is selected, go back to TabGroup1Activity if (and only if) the current activity is not that activity (basically you want to simulate a 'back' press).
If so, what you want is this:
if (getCurrentActivity().getClass() != TabGroup1Activity.class)
getCurrentActivity().finish()
I'm not 100% sure I understand you fully, but let's see :)
In your onTabChanged listener you can switch on which tab have been tabed, and then open the activity as normal inside an activitygroup:
public void onTabChanged(String tabId) {
if (tabId.contentEquals("tab1")) {
Intent intent = new Intent(tabHost.getContext(), TabGroup1Activity.class);
View view = StartGroup.group.getLocalActivityManager().startActivity("tab1", intent).getDecorView();
StartGroup.group.setContentView(view);
}
}
I just reviewed my code and think there's a bit more to explain here. The problem is that you don't stack activities as normal. Instead the workaround is to make a content stack and change these instead. So what I have done is to create a class StartGroup which extends
ButtonHandlerActivityGroup:
public class StartGroup extends ButtonHandlerActivityGroup {
// Keep this in a static variable to make it accessible for all the nested activities, lets them manipulate the view
public static StartGroup group;
// Need to keep track of the history if you want the back-button to work properly,
// don't use this if your activities requires a lot of memory.
private ArrayList<View> history;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.history = new ArrayList<View>();
group = this;
// Start the root activity within the group and get its view
View view = getLocalActivityManager().startActivity("UserList", new Intent(this, UserList.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)).getDecorView();
replaceView(view);
}
public void back() {
if (history.size() > 0) {
// pop the last view
history.remove(history.size()-1);
setContentView(history.get(history.size()-1));
} else {
finish();
}
}
}
Then from the TabMaster class or what you call it you can use the StartGroup class to change the content view of an activity group.
This is something I wrote to work on devices from 2.2, so there might be an easier and more androidish way to accomplished it, but this works on almost all devices :)
Here is another thread where the use a similar approach:
Launching activities within a tab in Android
Let me know if I can help more.
There is an ArrayList in your ActivityGroup so override onPause() method in ActivityGroup and remove all the ids from ArrayList except the first one which must be your SearchActivity.
So when you go to other tab then comes back to SearchActivity( or on Tab1 ) Home will be displayed.