I created a day/night mode switch system in my app. Currently, I use a PreferenceFragmentCompat + SharedPreference to display and save the switch selection.
This is my code:
public class PreferencesActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preferences);
PreferencesFragment preferencesFragment = new PreferencesFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.preferences_container, preferencesFragment).commit();
}
public static class PreferencesFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.preferences, rootKey);
}
#Override
public void onResume() {
super.onResume();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (isAdded()) {
if (sharedPreferences.getBoolean(getString(R.string.KEY_PREF_NIGHT_MODE), false)) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
}
}
}
}
On top of that, I use the following code in the OnCreate method of my main Activity:
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
int mode = sharedPreferences.getBoolean(getString(R.string.KEY_PREF_NIGHT_MODE), false) ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO;
if (AppCompatDelegate.getDefaultNightMode() != mode)
AppCompatDelegate.setDefaultNightMode(mode);
The problem is that when I activate the dark mode and I restart the application, it will launch then restart in the onCreate. Isn't there a more optimal way to implement this system?
you could create BaseActivity where you set the night mode
abstract class BaseActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
}
}
and then extend all your Activites from BaseActivity
public class PreferencesActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
}
}
then your night mode would be set in every activity before setContentView and no relaunch would be occured
UPDATE
change
#Override
public void onResume() {
super.onResume();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
to
#Override
public void onStart() {
super.onStart();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
onStart is called before view is visible
UPDATE 2
here is the singleton to access SharedPreferences
public class SharedManager {
private static SharedManager instance;
private final SharedPreferences preferences;
private SharedManager() {
preferences = MyApplication.getAppContext().getSharedPreferences(Constants.PREF_NAME, Context.MODE_PRIVATE);
}
public static SharedManager getInstance() {
if (instance == null) {
synchronized (SharedManager.class) {
if (instance == null) {
instance = new SharedManager();
}
}
}
return instance;
}
public SharedPreferences getPreferences() {
return preferences;
}
}
with call SharedManager.getInstance().getPreferences() you can get access to Preferences
Related
This question already has answers here:
How can I change language of whole application by only single click?
(3 answers)
Closed 2 years ago.
I want to change the Language of Application through strings.
here is my string folders
I want to change the Language of Application through strings.
So here is from my side. its works perfectly for me.
Follow these steps to change Language.
1.Save your strings in folder like values-ur(URDU)
than convert your all strings to that language you have to convert
2.Make a BaseActivity class and extend all your rest Activities to that Base class
public class BaseActivity extends AppCompatActivity
{
public BaseActivity context;
public MySharePreference mySharePreference;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
context = BaseActivity.this;
mySharePreference = MySharePreference.getInstance(context);
LocaleHelper.setLocale(context, mySharePreference.getLanguage() );
}
protected void attachBaseContext(Context base)
{
super.attachBaseContext(LocaleHelper.onAttach(base));
}
}
3.I have ExampleActivity that i want to translate its language.
public class ExampleActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
}
}
simply extend your application to your BaseActivity class.
3.Make a LocalHelper class in which it change the direction and strings.
public class LocaleHelper
{
public static Context setLocale(Context context, String language)
{
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = new Configuration(resources.getConfiguration());
configuration.setLayoutDirection(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
configuration.setLocale(locale);
LocaleList localeList = new LocaleList(locale);
LocaleList.setDefault(localeList);
configuration.setLocales(localeList);
}
else
{
configuration.locale = locale;
configuration.setLocale(locale);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1)
{
return context.createConfigurationContext(configuration);
}
else
{
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
public static Context onAttach(Context context)
{
return setLocale(context, MySharePreference.getInstance(context).getLanguage());
}
}
4.In your App class attach base context
public class AppClass extends MultiDexApplication
{
private static AppClass appClass;
public static AppClass getintance()
{
return appClass;
}
#Override
public void onCreate()
{
super.onCreate();
appClass = this;
MySharePreference.getInstance(this);
}
#Override
protected void attachBaseContext(Context base)
{
super.attachBaseContext(LocaleHelper.onAttach(base));
}
}
5.In your build.gradle file add latest androidx SharedPreferences dependency.
implementation 'androidx.preference:preference:1.1.1'
6.In my case i make my Own SharedPreferences class.
public class MySharePreference
{
private static MySharePreference instance;
private static SharedPreferences pref;
private MySharePreference(Context context)
{
if (context != null)
{
pref = PreferenceManager.getDefaultSharedPreferences(context);
}
else
{
pref = PreferenceManager.getDefaultSharedPreferences(App.getintance());
}
}
public static MySharePreference getInstance(Context context)
{
if (instance == null || pref == null)
{
instance = new MySharePreference(context);
}
return instance;
}
public String getLanguage()
{
return pref.getString("appLanguage", "en");
}
public void setLanguage(String b)
{
pref.edit().putString("appLanguage", b).apply();
}
}
7.At last save the abbreviation of that language to SharedPreferences in my case i have spinner.
spinner_lang.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
if (mySharePreference.getLanguagePosition() != position)
{
mySharePreference.setLanguage(Constants.COUNTRY_LIST.get(position).countryAbbr);
mySharePreference.setLanguagePosition(position);
startActivity(new Intent(mActivity, MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
}
}
#Override
public void onNothingSelected(AdapterView<?> parent)
{
}
});
now all done......
I have troubles on calling the method update from MainActivity class in a the MSG0100 non-activity class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void update(boolean msg100Preselection){
if(msg100Preselection){
mExpandableListViewAdapter.setSelectedChild(-1);
mExpandableListViewAdapter.notifyDataSetChanged();
}
}
}
And this is my class where i want to call the update method of Mainactivity.
public class MSG0100{
boolean msg100Preselection=false;
pulic void onUpdate(){
msg100Preselection=true;
// Want to call my update method here
MainActivity activity= new MainActivity();
activity.update(msg100Preselection); //<-------- Using mainactiviy object crashes my app.
}
}
What you want is impossible as you dont have a pointer to your main activity.
The following statement is invalid.
MainActivity activity= new MainActivity();
You are not allowed to use the new operator to create an activity. That should be done using an intent.
There are several things you could do:
Move your update method in another class
OR
declare your update method as static and use it like this:
MainActivity.update(msg100Preselection);
Try using a callbackListener :-
In your MSG0100 class
public class MSG0100 {
boolean msg100Preselection = false;
private static OnUpdateListener mListener;
public static setListener(OnUpdateListener mListener) {
this.mListener = mListener;
}
public void onUpdate() {
msg100Preselection = true;
if (mListener != null)
mListener.onUpdate(msg100Preselection);
}
public interface OnUpdateListener()
{
void onUpdate ( boolean msg100Preselection);
}
}
In your MainActivity-
public class MainActivity extends AppCompatActivity, OnUpdateListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MSG0100.setListener(this)
}
#Override
public void onUpdate(boolean msg100Preselection) {
if (msg100Preselection) {
mExpandableListViewAdapter.setSelectedChild(-1);
mExpandableListViewAdapter.notifyDataSetChanged();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
MSG0100.setListener(null)
}
}
This way you won't have any memory leaks or crashes due to Activity being killed.
I am trying to implement my own EditTextPreferenceDialogFragmentCompat. I would like to check if the user enter an IP address in the text field. If it's not the case, the user should not be able to validate the dialog. I have successfully shown my custom PreferenceDialogFragmentCompat, but I cannot save the text value anymore!
public class SettingsActivity extends AppCompatActivity {
public static final String PREF_IP_KEY = "ipDs1242_2";
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*
...
*/
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, new Preferences()).commit();
}
//A Fragment needs to be a public static class
public static class Preferences extends PreferenceFragmentCompat {
private EditTextPreference mIpModulePref;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(getClass().getSimpleName(), "onCreate() frag Prefrences");
}
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences_app);
Log.e(getClass().getSimpleName(), "onCreateFragment()");
mIpModulePref = findPreference(PREF_IP_KEY);
mIpModulePref.setSummary("Addresse IP : " + mIpModulePref.getText());
mIpModulePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Log.e(getClass().getSimpleName(), "new pref saved"); //never called...
return true;
}
});
mIpModulePref.setOnBindEditTextListener(this);
}
//shows my custom dialog
#Override
public void onDisplayPreferenceDialog(Preference preference) {
if (getFragmentManager().findFragmentByTag(DialogPreferenceFragment.TAG) != null) {
return;
}
if (preference instanceof EditTextPreference && preference.getKey().equals(PREF_IP_KEY)) {
DialogPreferenceFragment dialogPreferenceFragment = DialogPreferenceFragment.newInstance(PREF_IP_KEY);
dialogPreferenceFragment.setTargetFragment(this, DialogPreferenceFragment.REQUEST_CODE);
dialogPreferenceFragment.show(getFragmentManager(), DialogPreferenceFragment.TAG);
} else {
super.onDisplayPreferenceDialog(preference);
}
}
}
//the custom dialog to show
public static class DialogPreferenceFragment extends EditTextPreferenceDialogFragmentCompat {
public static final int REQUEST_CODE = 0;
public static final String TAG = "DialogPreferenceFragment_tag";
private Context mContext;
private EditTextPreference mEditTextPreference;
private SharedPreferences prefs;
public static DialogPreferenceFragment newInstance(String key){
Bundle bundle = new Bundle();
bundle.putString(ARG_KEY, key);
DialogPreferenceFragment dialogPreferenceFragment = new DialogPreferenceFragment();
dialogPreferenceFragment.setArguments(bundle);
return dialogPreferenceFragment;
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
mContext = context;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
}
#Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
Log.e(getClass().getSimpleName(), "restore pref IP");
mEditTextPreference = ((EditTextPreference) getPreference());
String txtValue = prefs.getString(mEditTextPreference.getKey(), ""); //reads the right value
mEditTextPreference.setText(txtValue);
}
#Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
builder.setMessage("Enter the IP address");
}
#Override
public void onDialogClosed(boolean positiveResult) {
if(positiveResult){
Log.e(getClass().getSimpleName(), "save pref IP");
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
editor.putString(mEditTextPreference.getKey(), mEditTextPreference.getText());
editor.commit();
String value = prefs.getString(mEditTextPreference.getKey(), ""); //DOESN'T SAVE THE VALUE !
Log.e(getClass().getSimpleName(), value);
}
}
}
}
I can read the right value in the the onBindDialogView() function, but I cannot save my value.
Do you have an idea of what I missed?
Thank you for your help.
I want to implement the ...
#Override
public void onBackPressed() {
}
However, I get an error message saying, "Annotations are not allowed here". I need this method to be implemented here. Is there an alternative?
public class supbreh extends Appbreh
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_breh);
if (myBundle != null) {
String name = myBundle.getString("workout");
ShowDetails(name);
}
}
private void ShowAbDetails(String mName) {
if(mName.equals("abs1")){
#Override
public void onBackPressed() { //"Not Allowed here"
}
}
void onBackPressed ()
Called when the activity has detected the user's press of the back
key. The default implementation simply finishes the current activity,
but you can override this to do whatever you want.
In here you can't declare this method inside another method .
Only override it in that one Activity
#Override
public void onBackPressed()
{
super.onBackPressed();
}
FYI
#Override
public void onBackPressed() {
Intent intent = new Intent(IndividualAbsWorkout.this, IndividualAbsWorkout.class);
startActivity(intent);
}
You can override onBackPressed as normal and call the method in ShowAbDetails() method like below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_breh);
if (myBundle != null) {
String name = myBundle.getString("workout");
ShowDetails(name);
}
}
private void ShowAbDetails(String mName) {
if(mName.equals("abs1")){
onBackPressed();
}
}
#Override
public void onBackPressed() {
// your logic here
}
How do I know the state of the ToggleButton from another activity?
i have class
public class MainScreen extends Activity{
protected ToggleButton tgbutton;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainscreen);
tgbutton = (ToggleButton)findViewById(R.id.advice);
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
tgbutton.setChecked(sharedPreferences.getBoolean("toggleButton", false));
}
public void oneClick(View v) {
if(tgbutton.isChecked() == false) { playSound(mSound); }
else { pauseSound(mSound); }
}
}
and
public class SmallprintA extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.smallprint_a);
OnClickListener SendOnClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
if(tgbutton.isChecked() == true){ playSound(mEmpty); }
else { playSound(mEmpty); }
}
};
}
I need in the class SmallprintA determine the state of the ToggleButton tgbutton. This is possible without class inheritance?
I did tgbutton is static
public class MainScreen extends Activity{
protected static ToggleButton tgbutton; // STATIC
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainscreen);
tgbutton = (ToggleButton)findViewById(R.id.advice);
}
public void oneClick(View v) {
if(tgbutton.isChecked() == false) { playSound(mSound); }
else { pauseSound(mSound); }
}
}
and
public class SmallprintA extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.smallprint_a);
OnClickListener SendOnClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
if(MainScreen.tgbutton.isChecked() == true){ playSound(mEmpty); }
else { playSound(mEmpty); }
}
};
}