Change source color file for dark mode programmatically Android

1.1k views Asked by At

I'm trying to implement dark mode for my application. I created two different file color.xml (the second with color of my dark mode). I saved in boolean if my switch is on/off using sharedPreferences, when I click the switch button color changed, but when I close my application e re-open it, returns the "normal" colors. I worked with fragments.

Settings Fragment


public class SettingsFragment extends Fragment {

    private Context mContext;
    private SharedPreferences sharedPreferences;

    private Spinner spinner;
    private LottieAnimationView darkModeOn, darkModeOff;
    private SwitchMaterial switchDarkMode;
    private RadioButton lightRadio, darkRadio;
    private RadioGroup radioGroup;

    private boolean isDarkModeOn;
    private boolean isDarkMap;
    private Fragment fragment;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        final View v =  inflater.inflate(R.layout.settings_fragment, container, false);

        mContext = getActivity().getApplicationContext();
        fragment = getActivity().getSupportFragmentManager().findFragmentByTag(getResources().getString(R.string.settings_fragment_tag));

        spinner = v.findViewById(R.id.radius_spinner);

        darkModeOn = v.findViewById(R.id.animationDarkModeOn);
        darkModeOff = v.findViewById(R.id.animationDarkModeOff);

        radioGroup = v.findViewById(R.id.radio_group_settings);
        lightRadio = v.findViewById(R.id.light_radio);
        darkRadio = v.findViewById(R.id.dark_radio);

        switchDarkMode = v.findViewById(R.id.switch_dark_mode);

        //SharedPreferences per darkMode e darkMap
        sharedPreferences = mContext.getSharedPreferences("settingsPref", Context.MODE_PRIVATE);

        final SharedPreferences.Editor editor = sharedPreferences.edit();

        isDarkModeOn = sharedPreferences.getBoolean("darkMode",false);

        //inizializza switch e animazione
        if (!isDarkModeOn){
            darkModeOn.setVisibility(View.VISIBLE);
            switchDarkMode.setChecked(false);
        }else {
            darkModeOff.setVisibility(View.VISIBLE);
            switchDarkMode.setChecked(true);
        }

        
        //switch dark mode on/off and save sharedPref
        switchDarkMode.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (!isDarkModeOn){
                    isDarkModeOn = true;

                    darkModeOff.setVisibility(View.GONE);
                    darkModeOn.setVisibility(View.VISIBLE);

                    darkModeOn.playAnimation();

                    darkModeOn.addAnimatorListener(new Animator.AnimatorListener() {
                        @Override
                        public void onAnimationStart(Animator animation) {

                        }

                        @Override
                        public void onAnimationEnd(Animator animation) {
                            darkModeOn.setVisibility(View.GONE);
                            darkModeOff.setVisibility(View.VISIBLE);
                            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
                            editor.putBoolean("darkMode", true).apply();
                            MainActivity.darkModeOn = isDarkModeOn;
                        }

                        @Override
                        public void onAnimationCancel(Animator animation) {

                        }

                        @Override
                        public void onAnimationRepeat(Animator animation) {

                        }
                    });

                }else {
                    isDarkModeOn = false;

                    darkModeOn.setVisibility(View.GONE);
                    darkModeOff.setVisibility(View.VISIBLE);

                    darkModeOff.playAnimation();

                    darkModeOff.addAnimatorListener(new Animator.AnimatorListener() {
                        @Override
                        public void onAnimationStart(Animator animation) {

                        }

                        @Override
                        public void onAnimationEnd(Animator animation) {
                            darkModeOff.setVisibility(View.GONE);
                            darkModeOn.setVisibility(View.VISIBLE);
                            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
                            editor.putBoolean("darkMode", false).apply();
                            MainActivity.darkModeOn = isDarkModeOn;
                        }

                        @Override
                        public void onAnimationCancel(Animator animation) {

                        }

                        @Override
                        public void onAnimationRepeat(Animator animation) {

                        }
                    });
                }

            }
        });


        return v;
    }

}

colors.xml, night version is equals with different colors

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#56ab2f</color>
    <color name="colorPrimaryDark">#56ab2f</color>
    <color name="colorAccent">#56ab2f</color>

    <!--  Color LightMode  -->
    <color name="colorChipSelected">#F44336</color>
    <color name="ghost_white">#F8F8FF</color>
    <color name="chipUnchecked">#56ab2f</color>
    <color name="white">#FFFFFF</color>
    <color name="black">#000000</color>
    <color name="defaultButtonBackgroud">#A6A6A6</color>
    <color name="dafaultTextColor">#808080</color>
    <color name="endColorGradient">#a8e063</color>
    <color name="centerColorGradient">#7FCD1F</color>
    <color name="textWhite">#FFFFFF</color>
    <color name="primaryAndWhite">#56ab2f</color>
    <color name="selectedAndWhite">#F44336</color>
    <color name="primaryAndSelected">#56ab2f</color>
    <color name="primaryAndEnd">#56ab2f</color>

    <!--  Color DarkMode  -->
    <color name="backgroundStrong">#212121</color>
    <color name="backgroundLight">#3d3d3d</color>


</resources>

MainActivity.java (onCreate)

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ......

        //SharedPreferences per Settings
        settingsSharedPreferences = getSharedPreferences("settingsPref", MODE_PRIVATE);
        darkModeOn = settingsSharedPreferences.getBoolean("darkMode", false);
        
        ......

    }

In MainActivity I tried to write something like this, but it doesn't work:

        if (!darkModeOn){
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
        }else {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
        }
1

There are 1 answers

1
MehranB On

You can have a class like so in a separate file named extensions:

abstract class ThemeManager {

    public static void set(Context context, String activeTheme) {
        int themeRecourseID = R.style.LightMode;
        if (activeTheme.equals("DarkMode")) {
            themeRecourseID = R.style.DarkMode;
        }
        context.setTheme(themeRecourseID);
    }
}

And then in you res/values/styles.xml define your styles like this:

<resources>

<!-- Base application theme. -->
    <!-- Light theme. -->
    <style name="LightMode" parent="Theme.AppCompat.Light.NoActionBar">

        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary2</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark2</item>
        <item name="colorAccent">@color/colorAccent2</item>
        
    </style>

    <!-- Dark theme. -->
    <style name="NightModeTheme" parent="Theme.AppCompat.NoActionBar">

        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

    </style>
</resources>

And in your colors.xml file:

<resources>
    <!-- Dark theme colors. -->
    <color name="colorPrimary">#353535</color>
    <color name="colorPrimaryDark">#252525</color>
    <color name="colorAccent">#FF3C00</color>
    

    <!-- Light theme colors. -->
    <color name="colorPrimary2">#FFFFFF</color>
    <color name="colorPrimaryDark2">#FFBB29</color>
    <color name="colorAccent2">#FFB728</color>
</resources>

Aaaaaand finally in every activity set the theme this way:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        //SET THE THEME HERE BEFORE SETTING THE CONTENTVIEW OF THE ACTIVITY
        ThemeManager.set(this, "DarkMode");

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    }
}