I have an Activity A with 2 tabs and each tab have its own Activity (B and C) . Activity B and Activity C each have 2 text fields . I want to save value of these text field in SharedPreferences when user changes tabs.
How can I do this?
What you probably want is save your activity state in onSaveInstanceState instead, like this:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(MY_KEY, myStringValue);
// ...
}
And then in onCreate:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// other stuff...
if(savedInstanceState != null) {
myStringValue = savedInstanceState.getString(MY_KEY);
}
}
Related
I'm using bottom navigation view and when I change the orientation portrait to landscape. And current item and fragment change to one, but he was two or another. How to save item's position?
You can do something similar to this
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("SelectedItemId", bottomNavigationView.getSelectedItemId());
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
int selectedItemId = savedInstanceState.getInt("SelectedItemId");
bottomNavigationView.setSelectedItemId(selectedItemId);
}
I now have 2 fragment, one fragment handle portrait mode then another handle landscape mode. But the problem is that when rotate from portrait to landscape then back to portrait. It will not show the same thing that show on the first portrait mode. Is there any code that can solve this problem?
This code is inside the fragment holder:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frag_holder);
FragmentManager fm = getSupportFragmentManager();
final Fragment fragment = Frag.newInstance(); //Portrait layout
final Fragment fragment2 = Frag2.newInstance(); //Landscape layout
int orientation = getResources().getConfiguration().orientation; //check whether is it portrait or landscape
if(orientation == Configuration.ORIENTATION_PORTRAIT){
Fragment fragTAG = fm.findFragmentByTag(TAG_P);
if(fragTAG == null){
Log.i("test","test");
fm.beginTransaction()
.replace(R.id.fragPlaceHolder, fragment, TAG_P)
.commit(); //Portrait
}
else{
fm.beginTransaction().replace(R.id.fragPlaceHolder,fragTAG).commit();
}
}
if(orientation == Configuration.ORIENTATION_LANDSCAPE){
Fragment fragTAG = fm.findFragmentByTag(TAG_L);
if(fragTAG == null){
fm.beginTransaction()
.replace(R.id.fragPlaceHolder, fragment2, TAG_L)
.commit(); //Landscape
}
else{
fm.beginTransaction().replace(R.id.fragPlaceHolder,fragTAG).commit();
}
}
}
}
Step 1:
Add Config changes in your activity
<activity android:name=".ui.createtasks.CreateTaskActivity"
android:configChanges="orientation|screenSize|keyboardHidden" > </activity>
Step 2:
Add your edit text values to onSaveInstanceState
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putCharSequence(KEY_TITLE, et_text.getText().toString());
}
Step 3:
Get your Saved edit text values through onViewStateRestored
#Override
public void onViewStateRestored(#Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
String savedTitle = null;
if (savedInstanceState != null) {
savedTitle = savedInstanceState.getString(KEY_TITLE);
et_text.setText(savedTitle);
}
}
You can either call setRetainInstance(True); in the onCreate() methods in both Fragments.
Or
to create a headless-Fragment(a Fragment with no UI) to cache data.
A third option will be to use onSaveInstanceState(Bundle outState) to cache data and re-display the data by using Bundle savedInstanceState in the onCreateView() method.
When there is activity rotation, the activity closed and reopen the onDestroy and onCreate are called.
if you want to save data and reload it in the other rotation you can do it with onSaveInstanceState method:
protected void onSaveInstanceState(Bundle outState)
for example:
#Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putString("name", "David");
outState.putInt("age", 17);
}
and reload the data in the onCreate
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
…
if(savedInstanceState != null)
{
savedInstanceState.getString("name");
savedInstanceState.getInt("age");
}
}
Add code in manifest file
<activity
android:name=".file_name"//add your activity name
android:label="label" //add label
android:configChanges="orientation|screenSize|keyboardHidden"
android:theme="#style/AppTheme.NoActionBar" />
I have the following scenario:
Activity A > Activity B
Activity A < Activity B
What i would like to do is keep the state of Activity A when clicking Activity B's back button.
Activity A code:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_details);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null)
{
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
// check for saved instance
if (savedInstanceState != null)
{
//restore saved values
}
else
{
//initialize members with default values
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
savedInstanceState.putString("typeID", typeID);
super.onSaveInstanceState(savedInstanceState);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
typeID = savedInstanceState.getString("typeID");
}
public boolean gotoActivityB(View view)
{
Intent intent = new Intent(getApplicationContext(), ActivityB.class);
startActivity(intent);
return false;
}
Activity B code:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_buy_item);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null)
{
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
//do some magic...
}
public boolean onOptionsItemSelected(MenuItem item)
{
Intent intent = new Intent(getApplicationContext(), ActivityA.class);
startActivity(intent);
return false;
}
Every time i go from Activity B to Activity A, savedInstanceState is equal to null, in other words, Activity A state isn't saved or restored.
What am i missing here?
!!SOLUTION!!
Based on #cybersam's answer, Activities maintain their state by default. So there is no need for the savedInstanceState. To solve my problem i only had to update my back button events to:
public boolean onOptionsItemSelected(MenuItem item)
{
finish();
return true;
}
As the documentation for onSaveInstanceState() states:
An example when onPause() is called and not
onSaveInstanceState(Bundle) is when activity B is launched in front of
activity A: the system may avoid calling onSaveInstanceState(Bundle)
on activity A if it isn't killed during the lifetime of B since the
state of the user interface of A will stay intact.
So you cannot assume that onSaveInstanceState() would be called on A just because B is launched in front of it. In fact, most of the time, it will not be.
[EDITED]
Your code for B seems to be calling startActivity() to "go back" to the prior activity. If you just want B to go back to the prior activity, you can (usually) just call finish() to exit B, which should allow A to reappear (with its state intact), since it will become the top Activity in the stack.
In my application Main_Activity contain four fragments. In one fragment (called mobile_fragment) whenever i click the button in fragment it will move to another activity, in that i need to get the one value and need to send that data to that fragment(mobile_fragment).
what i done is:
whenever i click the button in fragment i moved to activity and get the value and that value sent to main_Activity, after that in mobile fragment i accessed that variable (static declaration of variable in main_activity).
Now my problem is after getting the value in mobile_fragment, i already entered values in remaining edit text widgets are cleared (no text). how i get previously entered values?
please any one help me.
fragment
public class Mobile_Fragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
// TODO Auto-generated method stub
if (container == null) {
return null;
}
browseplans.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), BrowsePlans_Activity.class);
startActivity(intent);
}}
BrowseplansActivty:
Intent intent=new Intent(BrowsePlans_Activity.this,MainActivity.class);
intent.putExtra("Amount",amount);
startActivity(intent);
Main_Activity:
public class MainActivity extends FragmentActivity implements OnClickListener {
public static String TAG = "Main First Frag";
public static String contact_number, prepaid_amt;
Fragment fragment;
FragmentManager frgManager;
FragmentTransaction ft;
Bundle b = new Bundle();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initUI();
bindEvents();// now this is my changed one
Intent in=getIntent();
prepaid_amt=in.getStringExtra("Amount");
Log.v("TAG+AMOUNT",""+prepaid_amt);
}
}
To pass data from your fragment to the Activity you are starting, pass it through Intent Extras.
To return data from the Activity back to the fragment, call setResult with a result code and an intent that, again, holds data set with extras. Retrieve that data in the onActivityResult override of your fragment.
To save information in a fragment when it is detached and then re-attached, use the override onSaveInstanceState and then extract data from that state in onCreate and/or onCreateView overrides.
Backgroud: i have a menu on the left, and different scrollable contents on the right. i wanted to save the scrolled position. But i failed. Then ...
I have set up a very simple project to test it.
In words, i have a menu on the left, and different contents all holding an <EditText> on the right. (of the same class though, they are of different instances)
In codes, (very simple)
content.xml
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Please save my text ..." />
ContentFragment.java
package ... import ...
public class ContentFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.content, container, false);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
System.out.println("Why this is NOT called ?");
Log.v("onSaveInstanceState()", "outState = " + outState);
}
}
and the program generated MenuFragment.java
package ... import ...
public class MenuFragment extends ListFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, new String[]{"Item 1", "Item 2", "Item 3"}));
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
((MainActivity) getActivity()).click();
}
}
Lastly, our MainActivity.java
package ... import ...
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null)
getSupportFragmentManager().beginTransaction()
.add(R.id.menu, new MenuFragment()).commit();
}
public void click() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.content, new ContentFragment() // everytime load a new instance
).addToBackStack(null).commit();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
System.out.println("... and this is NOT called neither :-/");
Log.v("onSaveInstanceState()", "outState = " + outState);
}
}
To test it, please DO NOT rotate your device.
First, choose an item from the menu, then type something in the textbox. Then choose another item and type something again. Repeat for a few times. Then navigate back and ...
you will find your texts previously typed ARE SAVED !!!
It is not surprised that the texts are saved ...
But it is surprised the texts are saved with all the onSaveInstanceState() functions NOT called.
When did Android save them while replaced by FragmentTransaction?
If i want to additionally save some data into each Fragment instance (like the scroll position), where should i put my codes?
By default, Edittext save their own instance. See Yalla T.'s answer.
How to retain EditText data on orientation change?