简体   繁体   中英

How can I correctly to develop the dark mode in my Android studio?

I trying to deploy a switch button for switch the layout to light mode to dark mode, but I got some problem here. When I start the app, it can not auto switch to dark, I have switch to dark mode before I turn off the application before. And when I back to setting page, it will switch to dark mode, but here I got the error. The application got into a looping,

D/TagLifecycle: In the setting darkModeOff event
D/TagLifecycle: In the activity_main onDestroy() event
D/TagLifecycle: In the activity_main onCreate() event
D/TagLifecycle: In the activity_main onStart() event
D/TagLifecycle: In the activity_main onResume() event
D/TagLifecycle: In the activity_main onPause() event
D/TagLifecycle: In the activity_main onStop() event
D/TagLifecycle: In the activity_user_info onCreate() event
D/TagLifecycle: In the activity_setting onCreate() event
D/TagLifecycle: In the setting darkModeOn event
D/TagLifecycle: In the activity_setting onCreate() event
D/TagLifecycle: In the setting darkModeOff event
D/TagLifecycle: In the activity_main onDestroy() event
D/TagLifecycle: In the activity_main onCreate() event
D/TagLifecycle: In the activity_main onStart() event
D/TagLifecycle: In the activity_main onResume() event
D/TagLifecycle: In the activity_main onPause() event
D/TagLifecycle: In the activity_main onStop() event
D/TagLifecycle: In the activity_user_info onCreate() event
D/TagLifecycle: In the activity_setting onCreate() event
D/TagLifecycle: In the setting darkModeOn event
D/TagLifecycle: In the activity_setting onCreate() event
D/TagLifecycle: In the setting darkModeOff event

Here are my setting page code!

private Switch darkSwitch;

public static final String MyPREFERENCES= "nightModePrefs";
public static final String KEY_ISNIGHTMODE = "isNightMode";
SharedPreferences sharedPreferences;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_setting);
    Log.d(TAG_LIFECYCLE, "In the activity_setting onCreate() event");

    fbAuth = FirebaseAuth.getInstance();
    fbStore = FirebaseFirestore.getInstance();
    userID = fbAuth.getCurrentUser().getUid();

    sharedPreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
    darkSwitch = findViewById(R.id.swDark);

    checkNightModeActivated();

    darkSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if(isChecked) {
                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
                saveNightModeState(true);
                recreate();
                Log.d(TAG_LIFECYCLE, "In the setting darkModeOn event");
            } else {
                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
                saveNightModeState(false);
                recreate();
                Log.d(TAG_LIFECYCLE, "In the setting darkModeOff event");
            }
        }

    });

    BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_nav);

    bottomNavigationView.setSelectedItemId(R.id.settingActivity);
    bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
            switch (menuItem.getItemId()) {
                case R.id.mainActivity:
                    startActivity(new Intent(getApplicationContext(),MainActivity.class));
                    overridePendingTransition(0,0);
                    return true;
                case R.id.mapActivity:
                    startActivity(new Intent(getApplicationContext(),MapActivity.class));
                    overridePendingTransition(0,0);
                    return true;
                case R.id.userInfoActivity:
                    startActivity(new Intent(getApplicationContext(),UserInfoActivity.class));
                    overridePendingTransition(0,0);
                    return true;
                case R.id.settingActivity:
                    return true;
            }
            return false;
        }
    });
}
private void saveNightModeState(boolean nightMode) {
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putBoolean(KEY_ISNIGHTMODE, nightMode);
    editor.apply();
}
public void checkNightModeActivated(){
    if (sharedPreferences.getBoolean(KEY_ISNIGHTMODE, false)){
        darkSwitch.setChecked(true);
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
    } else {
        darkSwitch.setChecked(false);
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
        }
    }
}

There are quite some things that are wrong here and you can improve on it. I can tell you the reason why it is looping.

Here is where the problem lies:

When you first start you are checking up the night mode using this function call checkNightModeActivated();

Inside this function

public void checkNightModeActivated(){
    if (sharedPreferences.getBoolean(KEY_ISNIGHTMODE, false)){
        darkSwitch.setChecked(true);
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
    } else {
        darkSwitch.setChecked(false);
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
        }
    }
}

You are marking darkSwitch.setChecked(true); and further you have added an onCheckedListener for this which gets triggered when you mark it as true in here.

Inside the onCheckedListener which as follows:

darkSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if(isChecked) {
                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
                saveNightModeState(true);
                recreate();
                Log.d(TAG_LIFECYCLE, "In the setting darkModeOn event");
            } else {
                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
                saveNightModeState(false);
                recreate();
                Log.d(TAG_LIFECYCLE, "In the setting darkModeOff event");
            }
        }

    });

You are again recreating the whole activity, from where on checkNightModeActivated(); gets called again and we get looped.

The solution I would recommend for you is to shift the logic of initially checking and applying dark mode to your own personal class which extends the Application() class. Under it you can place the same logic of checking via SharedPreference and since Application() class remains through-out even if you recreate the activity, you would not get stuck. Note that you would need to register the said class in Manifest too.

Second suggestion would be to have some sort of button to confirm the change instead of directly on checkbox change.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM