I have TabActivity which contains 4 Tabs. Each tab have one FragmentActivity and 2-3 Fragments.
From Fragment, I am going to a Activity which is not the part of Tabs.
While clicking the Back button from that Activity, I want come back to previous Fragment,
without destroying that Activity.
I am overriding the public boolean onKeyDown(int keyCode, KeyEvent event) method, but problem is that it displays the previous fragment without Tabs. I want Tabs to be displayed...
Use onBackPressed method in your activity class.
#Override
public void onBackPressed(){
if(you wanto go back){
super.onBackPressed();
}else{
//if you dont want to go back
// do what you need hear....
}
}
What you have to do is, instead of using KeyCode Back, you have override the below method in your Activity,
#Override
public void onBackPressed() {
super.onBackPressed();
}
And save the state of your Button using SharedPrefrence, and next time when you enter your Activity get the value from the Sharedpreference and set the enabled state of your button accordingly.
Example,
private void SavePreferences(){
SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("state", button.isEnabled());
}
private void LoadPreferences(){
SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
Boolean state = sharedPreferences.getBoolean("state", false);
button.setEnabled(state);
}
#Override
public void onBackPressed() {
SavePreferences();
super.onBackPressed();
}
onCreate(Bundle savedInstanceState)
{
//just a rough sketch of where you should load the data
LoadPreferences();
}
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 an Activity with a ListView (ItemsActivity) which its contents come from a JSON API. When I press in one item in the ListView it loads another Activity with the details information (DetailActivity) . The problem is, when I press the Back Button, ItemsActivity reload the ListView again.
I don't know where I can find more information about this. I came from iOS where the previous screen is not reload every time.
I want to keep the ListView data between activities. I tested to call loadListItems() method from onResume() but same result.
Here is and brief sample of my code. Any help and suggestions will be really appreciated.
/* ItemsActivity.java */
public class ItemsActivity extends AppCompatActivity {
private ListView listItemView;
private Movie[] movies;
private ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler);
listItemView = (ListView) findViewById(R.id.listItemView);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
loadListItems();
}
private void loadListItems(){
// Http call
...
// Iterate JSON and saving to movies array
...
progressBar.setVisibility(INVISIBLE);
ListAdapter adapter = new ListAdapter(ItemsActivity.this, movies);
listItemView.setAdapter(adapter);
}
/* Adapter Class */
#Override
public void onClick(View v) {
Intent i = new Intent(this, DetailActivity.class);
i.putExtra("item_id", 1);
startActivity(i);
}
}
I just tested with a new Project with 2 Activities, ActivityOne and ActivityTwo. ActivityOne have a button, when a pressed its load ActivityTwo and when I press the back button, in ActivityOne the method onCreate() is called again.
You mentioned that "I tested to call loadListItems() method from onResume() but same result." This onResume() code is culprit.
OnResume() will get called whenever your activity gets focus again. If you are calling loadListItems() in onResume() then it will get called everytime you come back from your second activity to this activity.
http://developer.android.com/reference/android/app/Activity.html#onResume()
A solution is to use StartActivityForResult and not StartActivity. Then in the second activity, override the onBackPressed method and finish() the second activity within this method. Override the onActivityResult method in your first activity and this activity will be called and not the onCreate method and the ListView will not be reloaded.
The problem was only when I pressed the back button from Action Bar and I fix it with onOptionsItemSelected method.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
I have 2 Activity(s). Inside 1st Activity there is initially one Fragment
MainActivity.java
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myactivity);
if(savedInstanceState == null) {
getFragmentManager().beginTransaction().replace(R.id.fragmentContainer, MainFragment.newInstance().commit();
}
}
}
then clicking on a button replaces it with another Fragment.
#Override
public void onClick(View arg0) {
DetailFragment detail = (DetailFragment)getFragmentManager().findFragmentById(R.id.detail);
getFragmentManager().beginTransaction().replace(R.id.detail, detail, "detail").commit();
}
On 2nd Fragment there is another button, clicking on it opens a New Activity.
Intent popUp = new Intent(MainActivity.this, PopUp.class);
popUp.putExtra("CarID", carID);
startActivity(popUp);
From PopUp Activity, pressing device back will go back to MainActivity.
Now the challenge is for the Application's business logic I need to update the ActionBar's title of previous MainActivity when user goes back.
For this I'm listening for onResume() on both MainFragment and DetailFragment. Also when user goes back from DetailFragment to MainFragment I update the ActionBar title with different text.
So I need to know when exactly user goes back from:
1) PopUp Activity > Detail Fragment
2) Detail Fragment > Main Fragment
Currently onResume() is fired on both MainFragment and DetailFragment when PopUpActivity is closed. On MainFragment I can't exactly find out whether onResume() is called for 1st or 2nd case.
What is the best practice to fire onResume() on DetailFragment only when user goes back from PopUpActivity > DetailFragment. In other words, how do I detect from DetailFragment that PopUpActivity is closed without firing onResume() on MainFragment.
I wouldn't mess with onResume() for something like this.
I would suggest doing the following:
Create a Stack<String> for titles.
Implement FragmentManager.OnBackStackChangedListener in your MainActivity.
In your onBackStackChanged() implementation, check if the back stack has been pushed or popped using FragmentManager.getBackStackEntryCount().
If the back stack has been pushed, push the newly-displayed fragment's title to your title stack.
If the back stack has been popped, pop a title and set the title bar with the title at the new top of stack.
If you set a title from a fragment that isn't added to the back stack, pop a title from the title stack and push the newly-displayed fragment's title, i.e. replace the title at the top of the stack.
Invoke your PopupActivity with startActivityForResult() instead of startActivity().
Override onActivityResult() in your MainActivity so that when PopupActivity returns, you set the title bar with the title at the top of stack.
Don't forget to persist your title stack in onSaveInstanceState() in your MainActivity and restore it in onCreate().
That might seem like a lot of work just for maintaining titles, but you will drive yourself crazy trying to do this with onResume.
try it:
#Override
public void onResume() {
super.onResume();
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){
// handle back button
return true;
}
return false;
}
});
}
I want to go back to the last fragment in the back stack, so I want to make the back button popback the stack. Should I do this? and if so, should I override onBackPressed() or onKeyDown()?
#Override
public void onBackPressed()
{
Intent intent = new Intent(this,ABC.class);
startActivity(intent);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK ) {
// do something on back.
return true;
}
return super.onKeyDown(keyCode, event);
}
My fragments aren't being added to the back stack properly for some reason
I am using this to try to go back to the previous fragment, but the order is acting strange. What exactly should I do to make the order proper?
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft){
if(teamsFrag !=null)
{
if(manage.getBackStackEntryCount() > 0)
manage.popBackStack(manage.getBackStackEntryAt(manage.getBackStackEntryCount()-1).getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
//ft.detach(dataFrag);
}
Short answer? No.
Long answer? If you have to ask, No.
You should set your fragments up using the fragment manager so that the back button does what you want. You shouldn't override the back button instead of implementing your stack correctly.
I want to go back to the last fragment in the back stack, so I want to make the back button popback the stack.
This is the default behavior when you use FragmentTransaction#addToBackStack() while adding new Fragments with the FragmentManager.
I have 2 pages in my application. From Page A I am calling Page B. On page B I have a ListView which is filled by users. Now when User clicks on Back Button of the phone he comes back to Page A. But when he clicks menu and select Add Items again, it opens Page B but my ListView is empty. How can I get back to Page B without losing data in ListView?
Override the onBackPressed in page B, and save your data some where..
then in the onStart of page B reload the data..
One way to accomplish this is to use the SharedPreferences:
public void onStop(Bundle bundle)
{
SharedPreferences mySharedPreferences = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor editor = mySharedPreferences.edit();
editor.putBoolean("myBool",true);
//Continue saving all the data you need to recreate the listView
}
Then when you restart the activity, you can reload the preferences in the OnCreate() method like this:
public void onCreate(Bundle bundle)
{
SharedPreferences mySharedPreferences = getPreferences(MODE_PRIVATE);
// Retrieve the saved values.
boolean myBool = mySharedPreferences.getBoolean("myBool");
//Recreate the ListView here
}
It might not be the cleanest way to do so. But since onSavedInstanceState can't be used in your case, it will have to do :)
You can use SharedPreferences to save and load the data in a list
I.e
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
SharedPreferences settingsActivity = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor prefEditor = settingsActivity.edit();
prefEditor.putString(LISTFROMB, savedItems);
prefEditor.commit();
}
return super.onKeyDown(keyCode, event);
}
And then load it in A like :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple);
// Find the ListView resource.
mainListView = (ListView) findViewById(R.id.list);
ArrayList<String> selectedItems = new ArrayList<String>();
SharedPreferences settingsActivity = getPreferences(MODE_PRIVATE);
String savedItems = settingsActivity.getString(LISTFROMB, "");
selectedItems.addAll(Arrays.asList(savedItems.split(",")));
[CALL YOUR ADAPTER HERE WITH THE SELECTED ITEMS LIST]
}
Thanks for your help. I solved the problem just by declaring the ArrayList in Page A. So now when I go back to Page B the source of the ListView is in Page A so easy to load it back.
Don't know if this approach is wrong. Please leave your comment if you think this shouldn't be done.