How can I persist my theme settings in android app? - java

The theme changes in current activity(Settings Activity), but I have to restart the other background activities to apply the new theme. I'm thinking that the background activities should be restarted in the settings activity, but I can't find how.
This is my Settings Activity:
public class SettingsActivity extends FragmentActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
private SharedPreferences prefs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SettingsHelper.onActivityCreateSetTheme(this);
getSupportFragmentManager()
.beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
prefs = PreferenceManager.getDefaultSharedPreferences(this);
}
#Override
protected void onResume() {
super.onResume();
prefs.registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onPause() {
super.onPause();
prefs.unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("theme")) {
boolean isDark = prefs.getBoolean("theme", false);
prefs.edit().putBoolean("theme", isDark).apply();
SettingsHelper.changeToTheme(this);
}
}

switch (cTheme)
{
case BLACK:
int myTheme = R.style.Default
activity.setTheme(myTheme);
//Save your activity theme color
saveTheme(myTheme);
break;
case YELLOW:
int myTheme = R.style.Green
activity.setTheme(myTheme);
//Save your activity theme color
saveTheme(myTheme);
break;
}
and change your onActivityCreateSetTheme(Activity activity) to:
public static void onActivityCreateSetTheme(Activity activity, Int cTheme)
Save method
public void saveTheme(int theme)
{
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPreferences.edit();
prefEditor.putInt("Theme",theme);
}
Load method
public int loadTheme(){
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
//Load theme color
int theme = sharedPreferences.getInt("Theme",Color.RED); //RED is default color, when nothing is saved yet
return theme;
}
Important: call loadTheme() before setContentView() so your onCreate() should be like:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int theme = loadTheme(); //Load your theme here!!!!
CustomazationProcess.onActivityCreateSetTheme(this, theme);
setContentView(R.layout.something1);
findViewById(R.id.black).setOnClickListener(this);
findViewById(R.id.yellow).setOnClickListener(this);
}

The answer was indeed to recreate the activity but only after checking that the value got onCreate is different from the one onResume.
Link to a related SO question: Refresh(recreate) the activities in back stack when change locale at run time
#Override
protected void onCreate() {
super.onCreate()
preferences = PreferenceManager.getDefaultSharedPreferences(this);
isDark = preferences.getBoolean("theme", false);
}
#Override
protected void onResume() {
super.onResume();
if(isDark != preferences.getBoolean("theme", false))
recreate();
}

There is nothing called restart activity while it is in background and still keep it in background.
you can simply finish this activity so next start will be using the new theme.
or if your theme can be manually applied then you can apply the new theme at it's onResume (or onStart, depending on your logic).
You can also recreate the activity at onResume (if theme changed) but I don't recommend this as this resume will be unnecessary and you can simply use first option.

In all of your activities, try to put below code in onResume() method:
#Override
public void onResume(){
super.onResume();
boolean isDark = prefs.getBoolean("theme", false);
if(!isDark){
recreate();
}
}
recreate() needs to be invoked to recreate the activity so that the new theme can be applied on the current screen.

Related

How can i implement dark mode on the first activity while the application launched for the first time

I implement dark mode with SwitchPreference in the second activity and in the first activity just a button take me to the second activity (Setting) the problem is when the app destroyed and i launched it again the dark mode not implemented until the second activity launched.
//First Activity
public class MainActivity extends AppCompatActivity {
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences( this/* Activity context */);
Boolean theme = sharedPreferences.getBoolean("darkMode", false);
button=findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent2=new Intent(MainActivity.this,Settings.class);
startActivity(intent2);
}
});
}
}
i have some idea that i should use sharedpreferences but i don't know how can i set it
//Second Activity
public class MySettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(#Nullable Bundle savedInstanceState, #Nullable String rootKey) {
setPreferencesFromResource(R.xml.preferences,rootKey);
SwitchPreference switchPreference=findPreference("darkMode");
if (switchPreference.isChecked()){
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
}
}
Overview:-
You can change dark mode or light mode via this function.
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.HERE_YOUR_MODE);
You can access the mode like this:
AppCompatDelegate.MODE_NIGHT_YES // for dark mode
AppCompatDelegate.MODE_NIGHT_NO // for light mode
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM // for set as your devices theme
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM // when you are in battery saver
Implementation:-
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
Boolean theme = sharedPreferences.getBoolean("darkMode", false);
if (theme){
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); // implement here.
}else{
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); // implement here.
}
}
Well as per your code , you are just one step away from achieving result
you just need to use below code in every activity's onCreate method
if (isDarkMode){ // isDarkMode is boolean which we can get from preference
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
```

Change background using shared preference

I have an application that allows my users to customize the background of my application using buttons. My app works like this: First it will lead them to my main activity, where there is a button that they can press to customize the background. When they pressed that button, it will lead them to a dialog fragment that will give users an option to choose which background image they want. I'm able to change my background, however, the shared preference is not functioning correctly. When I close my app and open it, it changes back to my default background, but when I press the dialog fragment button, it then updates the background to whatever they chose.
So basically, the background only updates when I open the button that offers the background images.
I'm not sure if I explained it well so here is a gif of my
problem
The background only updates when I press the terrain button, does anyone have an idea to fix this? I'm still very new to android and java so I'm not sure if I'm just missing something...
PopupTheme.java
public class PopupTheme extends DialogFragment implements View.OnClickListener {
private ImageButton btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9, btn10;
private static final String BG_NAME = "bgName";
private static final String BG_KEY = "bg";
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.activity_popup_theme, container, false);
btn1 = view.findViewById(R.id.btn1);
btn2 = view.findViewById(R.id.btn2);
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
if (getBackground() != R.drawable.bgscreen1 ){
MainActivity.mainLayout.setBackgroundResource(getBackground());
}
return view;
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn1:
MainActivity.mainLayout.setBackgroundResource(R.drawable.bgscreen1);
Toast.makeText(getContext(), "Clicked", Toast.LENGTH_SHORT).show();
storeBackground(R.drawable.bgscreen1);
break;
case R.id.btn2:
MainActivity.mainLayout.setBackgroundResource(R.drawable.bgscreen2);
Toast.makeText(getContext(), "Clicked", Toast.LENGTH_SHORT).show();
storeBackground(R.drawable.bgscreen2);
break;
}
}
public void storeBackground(int background) {
SharedPreferences sharedPreferences = getActivity().getSharedPreferences(BG_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit(); //accessing the shared pref
editor.putInt(BG_KEY, background);
editor.apply();
}
// getting the background
public int getBackground() {
SharedPreferences sharedPreferences = getActivity().getSharedPreferences(BG_NAME, Context.MODE_PRIVATE);
int selectedBG = sharedPreferences.getInt(BG_KEY, R.drawable.bgscreen1);
return selectedBG;
}
}
Main Activity.java
public class MainActivity extends AppCompatActivity {
private Button btnWatch, btnReadStory, btnFavorites, btnAbout, btnListen;
private ImageButton btnTheme;
static ConstraintLayout mainLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnTheme = findViewById(R.id.btnTheme);
mainLayout = findViewById(R.id.layoutMain);
btnTheme.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PopupTheme popupTheme = new PopupTheme();
popupTheme.show(getSupportFragmentManager(), "Popup Theme");
}
});
}
}
The problem is that you update background of your MainActivity only if you opened the PopupTheme dialog, So you need to move getBackground and update code from PopupTheme to the onCreate method on MainActivity so the code will executed when the user launch the app
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnTheme = findViewById(R.id.btnTheme);
mainLayout = findViewById(R.id.layoutMain);
int background = getBackground();
if (background != R.drawable.bgscreen1 ){
mainLayout.setBackgroundResource(background);
}
// Other code on onCreate
}
// Move getBackground method here from PopupTheme
Note: you can use -1 as default value of background and check if it's -1 that mean the user use the default background

onclick listener for preference activity in Android

I was following this documentations to create a setting page. I have created two java classes based on the documentation:
SettingsFragment.java:
public static class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
...
}
SettingsActivity.java
public class SettingsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
}
In the preference I have an item with key premium_support which I want to create a click listener for it.
<CheckBoxPreference
android:key="#string/premium_support"
android:title="Premium Support"
android:summary="Purchase premium support"
android:defaultValue="false" />
I can't create a click listener in the fragment because I have my in app billing codes in the SettingsActivity. I tried this answer but seems like findPreference is only for the preferencefragment.
Any idea how to implement the click listener in SettingsActivity?
In the onCreate() method of SettingsActivity:
Preference preference = findPreference("prefs_key");
preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
Toast.makeText(SettingsActivity.this, "Clicked", Toast.LENGTH_SHORT).show();
return true;
}
});
The 'findPreference' method can only be called on the settingsfragment because it extends preferencefragment. You need to get a reference to the settingsfragment class in the settings activity like below:
private SettingsFragment settingsFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("SETTINGS");
//instantiate the settings fragment
settingsFragment= new SettingsFragment();
getFragmentManager().beginTransaction()
.replace(android.R.id.content, settingsFragment)
.commit();
}
You then override onResume and set the preferenceclicklistener in onresume and not oncreate because the commit() method is called asynchronously ( i.e the code does not execute immediately) and the preference value might be null if you call findpreference immediately after commiting the fragment transaction in oncreate.
#Override
protected void onResume() {
super.onResume();
Preference preference =
settingsFragment.findPreference(getString(R.string.pref_key));
preference.setOnPreferenceClickListener(new
Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
//respond to click events here
return true;
}
});
}

Reload SharedPreferences

I'm quite new to Android Prorgramming and have a problem understandig SharedPreferences.
I have a Main Activity and a Settings Activity.
I want to be able to change a SharedPreference (here called firstWaitTime) in the Settings Activity and work with it in the Main Activity.
I can Set the new value in the settings, but in the Main Activity i only see the new value when i close and reopen the app.
I Think i would need a OnPrefrenceChanged Listender but i have no idea how to implement it...
The Main one looks like this:
public class MainActivity extends ActionBarActivity {
//Radio Button
private int stufe;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences settings = this.getSharedPreferences("settings", Context.MODE_PRIVATE);
int firstWaitTime = settings.getInt("firstWaitTime", 12);
int secondWaitTime = settings.getInt("secondWaitTime", 8);
int thirdWaitTime = settings.getInt("thirdWaitTime", 6);
//TEST
final TextView test = (TextView) findViewById(R.id.test);
test.setText("" + firstWaitTime);
}
The Settings Activity looks like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
final SharedPreferences settings = this.getSharedPreferences("settings", MODE_PRIVATE);
//BUTTON
final EditText edit1 = (EditText) findViewById(R.id.edit1);
Button save=(Button) findViewById(R.id.savebtn);
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//prefs = getSharedPreferences(prefName, MODE_PRIVATE);
//SharedPreferences.Editor editor = prefs.edit();
SharedPreferences.Editor editor = settings.edit();
//---save the values in the EditText view to preferences---
editor.putInt("firstWaitTime", Integer.parseInt(edit1.getText().toString()));
//---saves the values---
editor.commit();
Toast.makeText(getBaseContext(), "Saved", Toast.LENGTH_SHORT).show();
}
});
}
What is the best way to achieve this?
onCreate() will not be called as Android hasn't killed the Activity. Try putting your code in onResume() instead. For more info read up on the Android Activity lifecycle.

How to maintain CheckBox state across the activities

How to maintain CheckBox state across the activities
I checked a CheckBox in FirstActivity.java but when i move back to FirstActivity.java from any other activity, say from SecondActivity.java..
Then, I am not getting my CheckBox as check which i checked earlier.
Using onSaveInstanceState & onRestoreInstanceState, see complete code below:-
public class FirstActivity extends Activity {
CheckBox cb1;
Button btnNext;
private boolean boolCheck1 = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
cb_cb1 = (CheckBox) findViewById(R.id.cb1);
btnNext = (Button) findViewById(R.id.btnNext);
// control status of body frame checkboxes
cb1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if(isChecked){
}
}
});
btnNext.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putBoolean("Enable", cb1.isChecked());
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
boolCheck1 = savedInstanceState.getBoolean("Enable");
}
}
Your best option is to use sharedPreferences.
In your activity where the checkbox is located, in your onCreate() put the following:
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 - for private mode
Editor editor = pref.edit();
Then, in your intent to go to another activity, or "save" button, or whatever you want, use the following:
editor.putBoolean("checkbox", yourCheckbox.isChecked());
editor.commit(); // commit changes
Now, the setting is saved.
When you come back to your activity, use this in your onCreate:
if (pref.getBoolean("checkbox", false) == true){ //false is default value
yourCheckbox.setChecked(true); //it was checked
} else{
yourCheckbox.setChecked(false); //it was NOT checked
}
You can read more here.
Hope this helped
Use SharedPreferences or SQLiteDatabase to store the value of check box and you can use it after fetching from Database or SharedPreference.
If you use onSaveInstanceState & onRestoreInstanceState all reference will clear when user close the app and the app is no longer in Memory.
Tutorial for SharedPreference
Tutorial for Database
To maintain state across activities you have to use SharedPreferences, or database. In your case SharedPreferences is the best option
You have used OnSavedInstance it will only save the instance until the activity is not destroyed i.e it stays on the stack.
Check activity lifecycle to understand more about when an activity is destroyed.
For each checkbox you can store its value in sharedPreference and on
onCreate() of you activity you should check the checkboxes according
to the sharedPreference values
Here is how you use shared prefs
SharedPreferences prefs= context.getSharedPreferences("myPrefs", 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("checkbox1", true);//true if checked
editor.commit();
// get stored value , if no value is stored then assume its false
prefs.getBoolean("checkbox1", false);

Categories