I have a tab-host with three activities and in each activity I have 4 buttons.
On each button press I am changing the background drawable resource like this
case R.id.button1:
if (isclick) {
b1.setBackgroundResource(R.drawable.icon4hlt);
} else {
b1.setBackgroundResource(R.drawable.icon4);
}
So now How can I save the pressed state of each button in all three child activities so that when I move from one activity to the other the button pressed state will be reflected on moving back.
first activity -> all 4 buttons pressed -> go to 2nd activity -> come back to first activity -> all buttons in first activity should be in pressed state
even on home button and back button press also It should work.
I know shared preferences is a good Idea and I went through related threads but I didnt get any Idea how to do this.
Any help is always appreciated,Thanks
You can keep ids of pressed buttons in shared preferences as you mentioned. You'll store a set of ids for every activity. Something like this:
public void onStop() {
SharedPreferences pref = // getPreferences;
Set<String> ids = new HashSet<String>();
for (Button button : buttons) {
if (button is pressed) {
ids.add(String.valueOf(button.getId()));
}
}
pref.edit().putStringSet(CURRENT_ACTIVITY_NAME, ids).commit();
}
public void onStart() {
SharedPreferences pref = // get preferences;
Set<String> ids = pref.getStringSet(CURRENT_ACTIVITY_NAME, Collections.emptySet<String>());
for (String id : ids) {
Button button = findViewById(Integer.parseInt(id));
set button pressed
}
}
But I still think pressed states should not reset when you switch between tabs because activity aren't recreated.
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 am creating an android application with three tabs using PageSlidingtabStrip as a library to create a swipe view.And it has three fragments.Each fragments has a list view.When the item of the listview is clicked it opens an activity and display the details.
The problem is how can i come back to the fragment in the main screen using back button in actionbar in the activity
And how can i go to the corresponding Fragment(Tab)
Try something like this :
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
Intent intent = new Intent(YourCurrentClass.this , ClassThatYouWantToGo.class);
startActivity(intent)
}
Or actually like #TommyTopas said, you can just Override onBackPressed and put this.finish();.
EDIT
As I've understood you want to use a button on your AcitonBar, then you have tod o something like this :
First set the HomeButton enabled doing :
getActionBar().setDisplayHomeAsUpEnabled(true); Then Override onOptionsItemSelected
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// or onBackPressed();
this.finish()
}
return true;
}
As I understand, when you return to the "Tab" Activity, you want to display the same tab in which the list item had been clicked. What you can do is, when a list item in any tab is clicked, save the tab number in onSavedInstanceState(), and when the Activity is recreated, then set the previously selected tab (if one was selected previously). You will get the savedInstanceState that you saved in onSavedInstanceState() back in the onCreate() of the same Activity.
You can provide an Up navigation by writing getActionBar().setDisplayHomeAsUpEnabled(true); and then in the onOptionsItemSelected method in the activity, if the item's id is android.R.id.home call the activity's method onBackPressed(); which will close your current activity and come back to your fragment
In the main activity ActivityA I replace FragmentA by fragment FragmentB. From FragmentB the user can start a new activity ActivityB. By hitting the back button in ActivityB, ActivityA is displayed showing FragmentA. I was expecting to see FragmentB with its last state. Do I have to save the state of the previous activities separately to provide this behaviour?
ActivityA(FragmentA) -> ActivityA(FragmentB) -> ActivityB
BACK
ActivityA(FragmentB)
In the main activity I set the current fragment using:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.a_main_frame_content, new FragmentB())
.addToBackStack(null)
.commit();
From the fragment I start a new activity using:
Intent intent = new Intent(getActivity(), ActivityB.class);
getActivity().startActivity(intent);
ActivityA is set as parent activity for ActivityB to provide proper navigation.
[UPDTATE] It looks like the problem lies in the different behaviour of navigating back and navigating up. If I navigate back, the activity is displayed in its last state while navigating up forces the activity to recreate.
Lets try this:
In the intent of the parentActivity(if you can set it before you create parentActivity its best, otherwise you may have to use setIntent):
currentActivityIntent.putExtra("random-unique-key-for-each-activity",
random-unique-key-for-each-activity);
And before you create a child activity, u put following in a map:
myKeyIntentMap.put(random-unique-key-for-each-activity, currentActivityIntent);
In the method triggered on "Up" event :
{
String parentKey = currentActivity.parentActivity.getIntent.getStringExtra("random-unique-key-for-each-activity");
Intent intentToLaunch = (Intent)myKeyIntentMap.get(parentKey);
intentToLaunch.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP );
startActivity(intentToLaunch);
}
This way, using the intent, even if your History Stack is A-someAct1-someAct2-B, and u launch intent resolving to A, it will be "brought to front" killing someActs.
P.S. I havent done any null checks and havent kept in mind the exact method names, just given you an approach.
Behaviour of "up" is sometimes misleading indeed. When I faced similar problem I preferred to save my time and not deal with saving states.
You can quickly solve it by catching your navigation "up" event in your Activity:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
}
return true;
}
This is happening because when you are moving to ActivityB activityA is going to puse and destroy state respectively, thus when you back to activity ActivityA ActivityA is starting again thus you are getting fragmentA as view. you need to save the state using sharedPfer. Use some flag to save the state in your onCreateView() check the state and set correct fragment for the view. Hope you have got my point.
public static final String PREFS_NAME = "mypref";
boolean isVisited;
//check sharedpref
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
isVisited= settings.getBoolean("isVisited", false);
if(!isVisited){
// set fragmentA
}else{
// set fragmentB
}
// inside fragment transaction block
Editor edit = settings.editor();
isVisited.setBoolean(true);
edit.commit();
I want to add a favorite button in a layout which can save the layout and apply it to another activity. I'll show you an image bellow to understand exactly the way I want to do it..
I created the favorite button, and the activity for this button to save the layout, but the app is still crashing when I press the favorite button and the activity which should open the layout, which I have saved, is blank. Here are the code:
public void onClick(View v){
SharedPreferences prefs = this.getSharedPreferences(
getApplicationContext().getPackageName(), Context.MODE_PRIVATE);
prefs.edit().putString("activity", "YourActivityName");
}
public void onClick(View v){
SharedPreferences prefs = this.getSharedPreferences(
getApplicationContext().getPackageName(), Context.MODE_PRIVATE);
String activityToRun = prefs.getString("activity", "noFavorites");
if(activityToRun.equals("noFavorites")
return null;
if(activityToRun.equals("YOUR FIRST ACTIVTY")
//code for launching activity
}
I added this to Favorite.java, and I created another activity, called Favorite2.java which should be open the layout saved by the favorite button, but what I don't understand is how I can link the saved layout to the activity Favorite2.java?
And please, if someone can tell me exactly the explanation for getString and putString and the way that they should be implemented.
I am trying to make an application which have 4 tabs at the bottom of the screen.
All of them contain Activity (Intent).
And I want to navigate any of the Activity to another activity. But want to keep the TabWidget visible.
Let me know as quickly as possible if you know about it.
Shaiful
The problem of error occuring due to the replacement of activities can be solved in the following manner.
First Let us understand the flow:
We have in a Tab host , activity (say a list) from which we need to go to the next Activity (say details for the clicked item) under the same tab. For this we can use the concept of replacing the activity.Also setting the flags for the tab selected and other for knowing that details are being shown now
When we press back we should get the previous activity under the same tab.For this instead of again replacing the activity we can refresh the tab while using the particular flag for tab which was selected. Also if flag for show details is true we'll go the the list in the same tab or else we will go the activity before the tabwidget (normal use of onBackPressed)
The code can be as follows..
For going from list to details...
(This can be in the onClickListener)
private OnClickListener textListener = new OnClickListener() {
#Override
public void onClick(View v) {
Constants.SHOW_DETAILS = true;
Intent intent = new Intent(context, DetailsActivity.class);
replaceContentView("activity3", intent);
}
};
public void replaceContentView(String id, Intent newIntent) {
View view = ((ActivityGroup) context)
.getLocalActivityManager()
.startActivity(id,
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
.getDecorView();
((Activity) context).setContentView(view);
}
When back pressed is done we override on BackPressed in each of the Activity under the tab to go to the list again from the details screen
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
if (MathHelper.SHOW_DETAILS) {
Log.e("back", "pressed accepted");
Constants.LIST_ACTIVITY = 1;
Constants.SHOW_DETAILS = false;
Intent intent = new Intent(this, Tab_widget.class);
startActivity(intent);
finish();
}
}
The most important part here is
Constants.LIST_ACTIVITY = 1; it indicates which tab we are in. so the corresponding activities will have its value as 0,1,2...etc
Again to load the correct list (Activty) when the tab activity is refreshed we have to include this in the TabWidget onCreate after the creation of the tabs
tabHost.setCurrentTab(Constants.LIST_ACTIVITY);
This is implemented in Tabs with multiple activities in a single tab.
However when multiple times activities are called StackOverFlow error arises. Tried very hard but unable to solve it.. Please someone tell a method to solve this problem
Also need to Replace an activity in a tab, However from child activity. How is that to be done?
At any one moment there may only be one activity. Docs about this here