How to save a Button drawable when rotating screen - java

I just read this: Saving Android Activity state using Save Instance State
this: Android - Open resource from #drawable String
My situation is: I have a Button background set when pressing it to be green with
button.setBackgroundResource(R.drawable.greenbutton);
How can I store this information with onSaveInstanceState and onRestoreInstanceState?
I tried: How to maintain a button style and click state after screen rotation? and worked but maybe there is something better than a three-nested-if-conditionals procedure? I mean I have to do this for 4+ Button and I think it a lot of work for just a simple cause :)
Thank you
EDIT: this is the code so far
package com.example.android.testbutton;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.change);
}
Button button;
Boolean click;
public void changeColor(View view) {
click = true;
button.setBackgroundResource(R.drawable.greenbutton);
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putBoolean("buttonClicked", click);
// etc.
super.onSaveInstanceState(savedInstanceState);
}
//onRestoreInstanceState
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
Boolean firstAnswer = savedInstanceState.getBoolean("buttonClicked");
{
if (savedInstanceState != null) {
if (savedInstanceState.containsKey("buttonClicked")) {
if (savedInstanceState.getBoolean("buttonClicked"))
button.setBackgroundResource(R.drawable.greenbutton);
//some codes to make the button becomes clicked.
}
}
}
}
}

set a variable on your activity too, and then save that and restore it with your state.
public class MyActivity extends Activity {
public static final String KEY_BUTTON_IS_GREEN = "isGreen";
boolean buttonIsGreen;
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_BUTTON_IS_GREEN, buttonIsGreen);
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
buttonIsGreen = savedInstanceState.getBoolean(KEY_BUTTON_IS_GREEN, false);
if (buttonIsGreen){
// find the button and set it green.
}
}
you'll need to add to your method that sets the button green and also set your variable = true if the button is green.

You have a few options:
You can set specific flags in AndroidManifest file:
<activity name= ".YourActivity" android:configChanges="orientation|screenSize"/>
It does not work by default because , when you change the orientation onCreate will be called again and it redraws your view. But If you set these flags and you are using a different layout for landscape mode, by adding these parameters the layout for landscape mode will not be called, because onCreate will not be called second time.
You can save int resources by:
int colorFirst = answerOne.getHighlightColor();
savedInstanceState.putInt("key", colorFirst);

Related

android.widget.Swtich - Keep state on pause?

I am a new developer writing an app that logs location when a switch is toggled. My switch works when I toggle it, but it loses it's state when I take the app out of the forefront. How do I keep the state of my android switch onPause and onResume?
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
// set view, initiate switch
Switch mainSwitch = (Switch) findViewById(R.id.mainSwitch);
// deal with switch
mainSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#SuppressLint("MissingPermission")
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// if switch is on
if (isChecked) {
logLocation();
}
} else if (!isChecked) {
stopLocation();
}
// true if the switch is in the On position
Log.v("#############=", "" + isChecked);
}
});
}
Adding an answer instead of continuing in the comments.
By default Android will save the state of your UI if and only if you're using default components (meaning TextView, Button, Switch etc.) and your component has an id. This state will only survive if the OS kills the app and the user returns to it. This means that if the user presses the Home button and then returns to your Activity at a later stage, the UI state of all default components of that specific Activity will be restored. When pressing the Home button the Activity is stopped and onSaveInstanceState is called, so here you get a chance to save any state that isn't maintained by default components or if you have some data you downloaded for instance that is used to populate your UI components with data.
If the user presses the Back button the app will be killed and any UI state won't be restored per default.
To overcome this, you can use SharedPreferences or any other local storage mechanism to store your UI state to disk basically.
I've added a snippet of code, that shows how you can use the different approaches.
In your case you don't need the onSaveInstanceState method implementation, as you have a default UI component, that knows how to save its own state already and as mentioned Android does this automagically for you already.
Both states (savedInstanceState and what goes into the SharedPreferences) should be restored in the onCreate method as this is always called whenever an Activity is re-created or created the first time, while onRestoreInstanceState might not be called all the time.
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getName();
private static final String CHECKBOX__STATE = "CHECKBOX__SAVE_STATE";
private Switch checkbox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkbox = findViewById(R.id.checkbox);
final boolean isChecked;
if (savedInstanceState != null) {
isChecked = savedInstanceState.getBoolean(CHECKBOX__STATE);
} else {
isChecked = PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean(CHECKBOX__STATE, false);
}
// Setting the state (if any) of the Switch.
checkbox.setChecked(isChecked);
checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Log.d(TAG, "onCheckedChanged: isChecked = true - log location");
} else {
Log.d(TAG, "onCheckedChanged: isChecked = false - stop logging location");
}
}
});
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(CHECKBOX__STATE, checkbox.isChecked());
}
#Override
protected void onDestroy() {
super.onDestroy();
PreferenceManager.getDefaultSharedPreferences(this)
.edit()
.putBoolean(CHECKBOX__STATE, checkbox.isChecked())
.apply();
}
}
I hope this helps :-)

Why do variable drawable and getDrawable(R.drawable.ic_launcher_background) refer to different objects respectively?

The code is very simple.
I want to change the image of a FrameLayout when clicking button.
The following statement is not working:
if(framgLay.getForeground() == getDrawable(R.drawable.ic_launcher_background)
So, I solved the problem with following code..
But, I don't know the reason why drawable and getDrawable(R.drawable.ic_launcher_background) refer to different objects respectively.
public class MainActivity extends AppCompatActivity {
FrameLayout fl1;
Drawable drawable;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fl1 = findViewById(R.id.fl1);
drawable = getDrawable(R.drawable.ic_launcher_background);
fl1.setForeground(drawable);
}
public void onClick(View v) {
if (fl1.getForeground() == drawable) {
fl1.setForeground(getDrawable(R.drawable.ic_arrow_drop_down_circle_black_24dp));
} else {
fl1.setForeground(drawable);
}
}
}
The reason is because when you call getDrawable(...) it will create new instance of that drawable which contains the same image, while the == will compare the references for those two instances. The solution is the following:
if (fl1.getForeground().pixelsEqualTo(drawable)) {
// here equals
}

Call function from Activity Class after preferences are updated Android

I would like to call a function from my main activity class after my preferences are updated, but I can't use onResume() because I have other classes that will trigger onResume (I believe).
Snippet from AndroidGPSTrackingActivity.java:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.settings:
startActivity(new Intent(this, SettingsActivity.class));
break;
}
return false;
}
SettingsActivity.java:
package com.example.gpstracking;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class SettingsActivity extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
After my preferences close, I want to call a function from my Main Activity, however it MUST be from my main activity because I need to send a context from my Main Activity. I've tried so much and just can't seem to get it.
onResume() is triggered when the Activity comes to the foreground. You should never be "triggering" onResume() other than leaving/returning to the Activity (if you're ever directly calling onResume(), you're doing it wrong).
Assuming you're needing to check for the updated value when you return to your Activity, then yes, onResume() is where you should probably do that. If the user returns to MainActivity after viewing SettingsActivity, then onResume() will be called, and you can check the updated preference value there.
EDIT: So I think honestly you'd be better off checking the preference values in onResume(), and not caching them globally. They aren't expensive to look up. Also, for immediate notifications, you could register a listener for preference changes, like so:
public class MainActivity extends Activity
implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerPreferenceListener();
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterPreferenceListener();
}
private void registerPreferenceListener() {
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this);
}
private void unregisterPreferenceListener() {
PreferenceManager.getDefaultSharedPreferences(this)
.unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
if ("the_key_i'm_interested_in".equals(key)) {
// Update stuff
}
}
}

CharSequence Restarts After Orientation Change

I have a CharSequence which displays a sequence of text after each imageview click however the CharSequence seems to restart if the orientation is changed mid sequence.
Does anyone know how this can be resolved?
On an orientation change the activity is restarted, and the inCreate() is called again. You have to take that in consideration.
A small example of how to store and retrieve a value:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
isStarted = savedInstanceState.getBoolean("isStarted");
}
}
#Override
protected void onResume() {
isStarted = true;
super.onResume();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean("isStarted", isStarted);
super.onSaveInstanceState(outState);
}
For more information and methods: Saving Android Activity state using Save Instance State
using android:configChanges="orientation|keyboardHidden|screenSize"> resolved the issue

Save the data and using it after restarting the app Android

I'm creating a simple app where the user can change the seekbar value. make the default value as 0 and setMax as 5. Every time the app is closed and started back, seekbar value is set to 0. How can I use and set the previous seekbar value which was set before closing the app.
Here's my Activity class >
public class MainActivity extends Activity {
SeekBar s;
TextView v;
public int n;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
s=(SeekBar)findViewById(R.id.seekBar1);
v=(TextView)findViewById(R.id.textView1);
next=(Button)findViewById(R.id.button1);
s.setProgress(n);
v.setText(n+" ");
s.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// TODO Auto-generated method stub
n = progress;
v.setText(n+" ");
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
v.setText(n+" ");
}
});
}
}
I Tried using onSaveInstanceState and onRestoreInstanceState but failed to restore back to the previous state.
Please Help
Thanks in Advance.
First of all, onSaveInstance and onRestoreInstance method are triggered only, when a destruction because of orientation change happens, hence you can not use this mechanism with that purpose, in order to store previous values after explicitly destroying the activity, you can use one of the persistance mechanisms that android provides. SharedPreferences or SQLiteDB saving them before destroying the activity, and restoring when the activity is started.
To get the latest value if any you have to add this code in onCreate method:
private SharedPreferences prefs;
private int progress;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
progress = prefs.getInt("myProgress", 0);
}
//And to store it all the time before the activity is destroyed you have to add this code in onPause:
protected void onPause() {
super.onPause();
Editor editPrefs = prefs.edit();
editPrefs.putInt("myProgress", newProgressValue);
editPrefs.commit();
}
Hope this helps.
Regards!
You might want to look at Storage Options in the Developers guide.
Specifically, Shared Preferences seems like a good place to start.
you can try to use SQL database, the database will be availble even after the app is closed and reopened

Categories