androidandroid-studiokotlinnativeandroid-dark-theme

Turn off dark mode on device programatically. (or other solution) Android studio Kotlin


So I need a little help here.

My problem is, that when I have a function in my app for changing to dark mode, then when I change it when the device is in light mode, it changes just fine, but when I change it when the device is in dark mode, it does not change some things (background and text).

I have found a solution, that when I disable dark mode in device options, it works just fine. I just want to change the app theme when you change it in the app, not when the device theme is changed, because it ruins it. This issue is not happening on Pixel 4 emulator, just on my POCO F2 Pro MIUI 12.5.5 phone.

themes.xml

<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Trieskask" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <!-- Primary brand color. -->
    <item name="colorPrimary">@color/primaryLightColor</item>
    <item name="colorPrimaryVariant">@color/primaryColor</item>
    <item name="colorAccent">@color/accentColorLight</item>
    <item name="colorOnPrimary">@color/primaryTextColor</item>
    <!-- Secondary brand color. -->
    <item name="colorSecondary">@color/secondaryLightColor</item>
    <item name="colorSecondaryVariant">@color/secondaryColor</item>
    <item name="colorOnSecondary">@color/secondaryTextColor</item>
    <!-- Status bar color. -->
    <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
    <!-- Customize your theme here. -->
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
    <item name="android:fitsSystemWindows">true</item>

    <item name="bottomNavigationStyle">@style/Widget.App.BottomNavigationView</item>
</style>

<!-- BottomNav style -->
<style name="Widget.App.BottomNavigationView" parent="Widget.MaterialComponents.BottomNavigationView.Colored">
    <item name="materialThemeOverlay">@style/ThemeOverlay.App.BottomNavigationView</item>
</style>

<style name="ThemeOverlay.App.BottomNavigationView" parent="">
    <item name="colorPrimary">@color/secondaryLightColor</item>
    <item name="colorOnPrimary">@color/primaryTextColor</item>
</style>

<!-- Cards style -->
<style name="Widget.App.CardView" parent="Widget.MaterialComponents.CardView">
    <item name="materialThemeOverlay">@style/ThemeOverlay.App.Card</item>
    <item name="shapeAppearance">@style/ShapeAppearance.App.MediumComponent</item>
</style>

<style name="ThemeOverlay.App.Card" parent="">
    <item name="colorSurface">@color/primaryColor</item>
    <item name="colorOnSurface">@color/primaryTextColor</item>
</style>

<style name="ShapeAppearance.App.MediumComponent" parent="ShapeAppearance.MaterialComponents.MediumComponent">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">8dp</item>
</style>

<!-- Appbar style -->
<style name="Widget.App.Toolbar" parent="Widget.MaterialComponents.Toolbar.Primary">
    <item name="materialThemeOverlay">@style/ThemeOverlay.App.Toolbar</item>
    <item name="titleTextAppearance">@color/primaryTextColor</item>
    <item name="subtitleTextAppearance">@color/primaryTextColor</item>
</style>

<style name="ThemeOverlay.App.Toolbar" parent="">
    <item name="colorPrimary">@color/secondaryLightColor</item>
    <item name="colorPrimaryVariant">@color/secondaryLightColor</item>
    <item name="colorOnPrimary">@color/primaryTextColor</item>
</style>

<style name="Widget.App.MaterialDivider" parent="Widget.MaterialComponents.MaterialDivider">
    <item name="materialThemeOverlay">@style/ThemeOverlay.App.MaterialDivider</item>
</style>

<!-- Divider style -->
<style name="ThemeOverlay.App.MaterialDivider" parent="">
    <item name="colorOnSurface">@color/primaryTextColor</item>
</style>

night/themes.xml

<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Trieskask" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <!-- Primary brand color. -->
    <item name="colorPrimary">@color/primaryDarkColor</item>
    <item name="colorPrimaryVariant">@color/primaryColor</item>
    <item name="colorAccent">@color/accentColorDark</item>
    <item name="colorOnPrimary">@color/secondaryTextColor</item>
    <!-- Secondary brand color. -->
    <item name="colorSecondary">@color/secondaryDarkColor</item>
    <item name="colorSecondaryVariant">@color/secondaryColor</item>
    <item name="colorOnSecondary">@color/primaryTextColor</item>
    <!-- Status bar color. -->
    <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
    <!-- Customize your theme here. -->
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
    <item name="android:fitsSystemWindows">true</item>
</style>

<!-- BottomNav style -->
<style name="Widget.App.BottomNavigationView" parent="Widget.MaterialComponents.BottomNavigationView.Colored">
    <item name="materialThemeOverlay">@style/ThemeOverlay.App.BottomNavigationView</item>
</style>

<style name="ThemeOverlay.App.BottomNavigationView" parent="">
    <item name="colorPrimary">@color/secondaryDarkColor</item>
    <item name="colorOnPrimary">@color/secondaryTextColor</item>
</style>

<!-- Cards style -->
<style name="Widget.App.CardView" parent="Widget.MaterialComponents.CardView">
    <item name="materialThemeOverlay">@style/ThemeOverlay.App.Card</item>
    <item name="shapeAppearance">@style/ShapeAppearance.App.MediumComponent</item>
</style>

<style name="ThemeOverlay.App.Card" parent="">
    <item name="colorSurface">@color/secondaryColor</item>
    <item name="colorOnSurface">@color/secondaryTextColor</item>
</style>

<style name="ShapeAppearance.App.MediumComponent" parent="ShapeAppearance.MaterialComponents.MediumComponent">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">8dp</item>
</style>

<!-- Appbar style -->
<style name="Widget.App.Toolbar" parent="Widget.MaterialComponents.Toolbar.Primary">
    <item name="materialThemeOverlay">@style/ThemeOverlay.App.Toolbar</item>
    <item name="titleTextAppearance">@color/secondaryTextColor</item>
    <item name="subtitleTextAppearance">@color/secondaryTextColor</item>
</style>

<style name="ThemeOverlay.App.Toolbar" parent="">
    <item name="colorPrimary">@color/secondaryDarkColor</item>
    <item name="colorPrimaryVariant">@color/secondaryDarkColor</item>
    <item name="colorOnPrimary">@color/secondaryTextColor</item>
</style>

<style name="Widget.App.MaterialDivider" parent="Widget.MaterialComponents.MaterialDivider">
    <item name="materialThemeOverlay">@style/ThemeOverlay.App.MaterialDivider</item>
</style>

<!-- Divider style -->
<style name="ThemeOverlay.App.MaterialDivider" parent="">
    <item name="colorOnSurface">@color/secondaryTextColor</item>
</style>

MainActivity.kt (where the dark and light mode switch happens

class MainActivity : BaseActivity() {

private lateinit var binding: ActivityMainBinding

private val profileFragment = ProfileFragment()
private val productsFragment = ProductsFragment()
private val aboutFragment = AboutFragment()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    replaceFragment(productsFragment)

    binding.bottomNavigation.menu.getItem(1).isChecked = true

    binding.bottomNavigation.setOnNavigationItemSelectedListener {
        when(it.itemId) {
            R.id.page_1 -> replaceFragment(profileFragment)
            R.id.page_2 -> replaceFragment(productsFragment)
            R.id.page_3 -> replaceFragment(aboutFragment)
        }
        true
    }
    val appSettingsPrefs: SharedPreferences = getSharedPreferences("AppSettingsPrefs", 0)
    val sharedPrefsEdit: SharedPreferences.Editor = appSettingsPrefs.edit()
    val isNightModeOn: Boolean = appSettingsPrefs.getBoolean("NightMode", false)

    if (isNightModeOn) {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
        binding.switchBtn.setBackgroundResource(R.drawable.ic_sun)
    } else {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
        binding.switchBtn.setBackgroundResource(R.drawable.ic_moon)
    }

    binding.switchBtn.setOnClickListener(View.OnClickListener {
        if (isNightModeOn) {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
            sharedPrefsEdit.putBoolean("NightMode", false)
            sharedPrefsEdit.apply()
            binding.switchBtn.setBackgroundResource(R.drawable.ic_moon)
        } else {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
            sharedPrefsEdit.putBoolean("NightMode", true)
            sharedPrefsEdit.apply()
            binding.switchBtn.setBackgroundResource(R.drawable.ic_sun)
        }
    })

}

private fun replaceFragment(fragment: Fragment) {
    if (fragment != null) {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.fragment_container, fragment)
        transaction.commit()
    }
}

And here you have some reference images

device in light mode and app too

device In light mode and app in dark

device in dark mode and app in light (bad)

device in dark mode and app too

PLEASE HELP


Solution

  • Keep this in your both themes file-

    <item name="android:forceDarkAllowed" tools:targetApi="q">false</item>
    

    so that device settings can't override app settings