I am trying creating an app on Android. When a user click on a button, the background color of the button changes to red. However, when I rotate the screen, the background color changes back to the original color.
I've used button.setBackgroundResource(R.drawable.button_red) to change the background to red when the user clicked on the button. I am trying to use onSaveInstanceState(Bundle savedInstanceState) to maintain the same background color and clicked state of the button after the screen rotation, but I don't know how to approach this.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(ANSWER_ONE_BUTTON_ISCLICKED, true);
super.onSaveInstanceState(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
if (savedInstanceState != null) {
button.setBackgroundResource(R.drawable.button_red);
//some codes to make the button becomes clicked.
}
}
Thanks!
Maintain a boolean that changes on the onClick of the button and save it on onSaveInstanceState like
#Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
savedInstanceState.putBoolean(ANSWER_ONE_BUTTON_ISCLICKED, isButtonOneClicked);
super.onSaveInstanceState(savedInstanceState);
}
and on onCreateView check like this
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState)
{
if (savedInstanceState != null)
{
if (savedInstanceState.containsKey(ANSWER_ONE_BUTTON_ISCLICKED))
{
if (savedInstanceState.getBoolean(ANSWER_ONE_BUTTON_ISCLICKED))
button.setBackgroundResource(R.drawable.button_red);
else
button.setBackgroundResource(R.drawable.original_color);
}
//some codes to make the button becomes clicked.
}
}
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);
}
Any time the main Activity is started or restarted (i.e. by pressing the home button on my action bar), all of the buttons (which reside in a fragment in this main activity) work correctly. However, if I press one of the buttons, then press the back button, the home fragment and its buttons reappears but none of the button callbacks work. The button images continue to change appearance when pressed, as always.
The callbacks are assigned in the onCreateView method of the home fragment, as follows:
public class HomeFragment extends SherlockFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Button button = (Button) v.findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Log.d(TAG, "Button!");
mActivity.getSupportFragmentManager().beginTransaction()
.replace(R.id.contFragMain, new SomeFragment())
.addToBackStack(null)
.commit();
}
});
}
Here is the superclass of Fragments I launch with the buttons:
public abstract class RouteListFragment extends SherlockFragment {
private static final String TAG = RouteListFragment.class.getName();
private Activity mActivity; // parent activity
RouteListAdapter mAdapter;
ListView mListViewRouteList;
public RouteListFragment() {
super();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = getActivity();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle bndl = getArguments(); // data passed should contain search term
View v = inflater.inflate(R.layout.fragment_route_list, container, false);
mListViewRouteList = (ListView) v.findViewById(R.id.listViewRouteList);
addRoutesToList(); //Populates the list with data via an async DB call
return v;
}
You shouldn't be stashing the Activity reference; the Activity is probably getting recreated at some point (depends on how your flow is), but you should either reassign the reference in onAttach (Activity activity), or just call getActivity() to get the currently Activity you're attached to.
So mActivity.getSupportFragmentManager()...
should instead be
getActivity().getSupportFragmentManager()...
EDIT: Wait, maybe that's not right. What is v in onCreateView()? You're not creating any UI in this Fragment? You should be using onViewCreated() to get a reference to the views in the created hierarchy.
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?
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Android fragments setRetainInstance(true) not works (Android support library)
I wrote a simple test project, but I cant understand why I always receive savedInstanceState = null in lifecycle methods onCreate, onCreateView and onActivityCreated. I change the screen orientation, see the log, but state not saved.
Tell me please where is my mistake.
Thanks.
The code of fragment class is:
public class TestFragment extends Fragment {
private String state = "1";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (savedInstanceState != null) {
//never works
state = savedInstanceState.getString("state");
}
//always prints 1
Toast.makeText(getActivity(), state, Toast.LENGTH_SHORT).show();
return inflater.inflate(R.layout.fragment_layout, container, false);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("state", "2");
Log.e("", "saved 2");
}
}
EDIT
When i try to use setRetainInstance i have no result again((( I change a state to 2 using btn1, but after changing orientation i see 1 when pressing on btn2. Help please(
public class TestFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
setRetainInstance(true);
super.onCreate(savedInstanceState);
}
private String state = "1";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout, container, false);
//button for changing state
((Button)view.findViewById(R.id.button1)).setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
state = "2";
}
});
//button for showing state
((Button)view.findViewById(R.id.button2)).setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
Toast.makeText(getActivity(), state, Toast.LENGTH_SHORT).show();
}
});
return view;
}
}
I have seen the same issue. But you can save the instate state in an other way, thanks to the method setRetainInstance(true), all your class data are saved automatically.
#Override
public void onCreate(Bundle savedInstanceState) {
setRetainInstance(true);
super.onCreate(savedInstanceState);
}
EDIT
Try to also add these params when you declare your activities :
<activity
android:name="MyActivity"
android:configChanges="orientation|keyboardHidden|screenSize" />
I was following tutorials on how to make Tabs using fragments.
each tab has this in the java files:
public class rdfri extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null) {
// We have different layouts, and in one of them this
// fragment's containing frame doesn't exist. The fragment
// may still be created from its saved state, but there is
// no reason to try to create its view hierarchy because it
// won't be displayed. Note this is not needed -- we could
// just run the code below, where we would create and return
// the view hierarchy; it would just never be used.
return null;
}
return (LinearLayout)inflater.inflate(R.layout.rdfri, container, false);
}
}
I would like to try and get a imageButton in the fragment. I figured image bottons work with this code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.rdmon);
ImageButton rainbowbook = (ImageButton) findViewById(R.id.imageButton1);
rainbowbook.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = Intent(rdmon.this, RainbowBookActivity.class);
rdmon.this.startActivity(myIntent);
}
});
}
So how would I go about getting the button code in the fragment code?
Thanks.
Put the button code in the overridden onActivityCreated method in your fragment class.
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ImageButton rainbowbook = (ImageButton) findViewById(R.id.imageButton1);
rainbowbook.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = Intent(rdmon.this, RainbowBookActivity.class);
rdmon.this.startActivity(myIntent);
}
});
}
This assumes of course that your imagebutton is contained in your fragment layout.