Как сохранить состояние темного режима в Android, когда приложение полностью закрыто
У меня небольшая проблема. Когда я включаю темный режим в своем приложении, а затем полностью закрываю приложение в Android, когда я снова открываю его, оно возвращается в светлый режим. Для этого я использую AppCompatDelegate. У меня есть фрагмент настроек с переключателем для включения или выключения темного режима, и он хорошо работает. У меня есть общие настройки для этого фрагмента переключателя, и он работает. Единственная проблема заключается в том, что остальная часть приложения не остается в темном режиме после полного закрытия, а затем снова открывается. Есть ли способ сохранить, а затем восстановить темный режим, когда я закрою и снова открою его?
Вот мой код для MainActivity:
package com.barzalou.lpapineau.test;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.Menu;
import com.barzalou.lpapineau.test.ui.CheckedChangeCallback;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.navigation.NavigationView;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
public class MainActivity extends AppCompatActivity implements CheckedChangeCallback {
private AppBarConfiguration mAppBarConfiguration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow, R.id.nav_maps)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_exit) {
finish();
System.exit(0);
}
return false;
}
public void onCheckedChange(boolean isChecked) {
if (isChecked) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
Log.d("Dark Mode Switch State", "On");
}
else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
Log.d("Dark Mode Switch State", "Off");
}
}
Вот мой код для SettingsFragment:
package com.barzalou.lpapineau.test.ui.settings;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import com.barzalou.lpapineau.test.R;
import com.barzalou.lpapineau.test.ui.CheckedChangeCallback;
import android.content.Context;
import static android.content.Context.MODE_PRIVATE;
public class SettingsFragment extends Fragment {
private SettingsViewModel settingsViewModel;
private static Switch DarkMode;
private boolean SwitchOnOff;
private CheckedChangeCallback callback = null;
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
settingsViewModel = ViewModelProviders.of(this).get(SettingsViewModel.class);
View root = inflater.inflate(R.layout.fragment_settings, container, false);
final TextView textView = root.findViewById(R.id.text_settings);
settingsViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
textView.setText(s);
}
});
return root;
}
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
DarkMode = (Switch) getView().findViewById(R.id.DarkModeSwitch);
DarkMode.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
callback.onCheckedChange(isChecked);
}
});
}
public void onAttach(final Activity activity) {
super.onAttach(activity);
if (activity instanceof CheckedChangeCallback) {
this.callback = (CheckedChangeCallback) activity;
}
}
public void onDetach() {
super.onDetach();
callback = null;
}
//Save and Restore Switch, Buttons, Textboxs, etc -----------------------
@Override
public void onStop() {
super.onStop();
try {
saveData();
Log.d("Data Save", "Data was saved");
} catch (Exception e) {
Log.d("Data Save", "Data could not be saved");
}
}
@Override
public void onStart() {
super.onStart();
try {
loadData();
updateViews();
Log.d("Data Restore", "Data was restored");
} catch (Exception e) {
Log.d("Data Restore", "Data was not able to get restored");
}
}
//------------------------------------------------------------------------
// Save data, load data and update views functions -----------------------
public void saveData() {
SharedPreferences sharedPreferences = getContext().getSharedPreferences("SharedPrefs", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
// Add other Switches, Buttons, Texboxes, etc to save
editor.putBoolean("SwitchState", DarkMode.isChecked());
// Example: editor.putString("String1", textview.getText().toString());
//---------------------------------------------------
editor.apply();
}
public void loadData() {
SharedPreferences sharedPreferences = getContext().getSharedPreferences("SharedPrefs", MODE_PRIVATE);
SwitchOnOff = sharedPreferences.getBoolean("SwitchState", true); //Change true to false to make the switch on by default
}
public void updateViews() {
DarkMode.setChecked(SwitchOnOff);
}
//------------------------------------------------------------------------
}
3 ответа
Я нашел простой и прямой ответ. Я тестировал это несколько раз, чтобы убедиться. Просто добавьте следующие переменные в MainActivity:
int NightMode;
SharedPreferences sharedPreferences;
SharedPreferences.Editor editor;
После этого вы захотите добавить следующие строки в метод MainActivity OnCreate():
sharedPreferences = getSharedPreferences("SharedPrefs", MODE_PRIVATE);
NightMode = sharedPreferences.getInt("NightModeInt", 1);
AppCompatDelegate.setDefaultNightMode(NightMode);
И чтобы закончить это, сохраните все свои переменные в общих настройках с помощью метода OnSaveInstanceState:
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
NightMode = AppCompatDelegate.getDefaultNightMode();
sharedPreferences = getSharedPreferences("SharedPrefs", MODE_PRIVATE);
editor = sharedPreferences.edit();
editor.putInt("NightModeInt", NightMode);
editor.apply();
}
Это все, что вам нужно сделать, чтобы сохранить состояние темного режима всего вашего приложения, даже когда приложение завершено или убито ОС.
Вы должны установить это в Application
с onCreate()
метод
class MyApp : Application() {
@Override
public void onCreate() {
super.onCreate();
boolean isNightMode = sharedPreferences.getBoolean("SwitchState", true);
if (isNightMode) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
}
}
Не забываем добавить AndroidManifest
<application
android:name=".MyApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
(этот код находится в котлине)
в начале приложения (любого) вставьте этот код в основное действие / всплеск активности
private lateinit var sharedPreferences: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sharedPreferences = getSharedPreferences(getString(R.string.app_name), MODE_PRIVATE)
when (sharedPreferences.getInt("night_mode", 2)) {
0 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
1 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
else -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
}
Инициализация диалогового окна onclick выполняется с использованием приведенного ниже кода с использованием общих настроек для изменения темы.
private fun themeDialog() {
val items = arrayOf("Light", "Dark", "Auto (System Default)")
var checkedItem = sharedPreferences.getInt("night_mode", 2)
MaterialAlertDialogBuilder(this)
.setTitle("Theme")
.setPositiveButton("Ok") { dialog, which ->
when (checkedItem) {
0 ->{
sharedPreferences.edit().putInt("night_mode", 0).apply()
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)}
1 -> {
sharedPreferences.edit().putInt("night_mode", 1).apply()
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)}
else -> {
sharedPreferences.edit().putInt("night_mode", 2).apply()
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
}
}
.setSingleChoiceItems(items, checkedItem) { dialog, which ->
checkedItem = which
}
.setCancelable(false)
.show()
}
использовал кнопку для вызова themeDialog()
findViewById<Button>(R.id.themeChangeBtn).setOnClickListener {
themeDialog()
}