Android - System doesn't recognize my theme as dark mode - android

I have two themes. One is:
<style name="ThemeDay" parent="Theme.AppCompat.Light.NoActionBar">
Other one is:
<style name="ThemeNight" parent="Theme.AppCompat.DayNight.NoActionBar">
I apply themes in every activity like this before super.onCreate()
if(GenelUtil.getNightMode()){
setTheme(R.style.ThemeNight);
}else{
setTheme(R.style.ThemeDay);
}
Theme is applied. But system doesnt behave like selected theme.
For example when system is light mode and app is dark mode, Navigation bar is still white, dialogs are still white etc..
But when I open instagram and switch to dark mode, system also behave like its in dark mode.
What do I do wrong here? How can I fix this?

DayNight theme is picking automatically dark or light params/colors basing on system settings (by default) or set/forced by you (e.g. using AppCompatDelegate.setDefaultNightMode())
when you have light theme in your system and you will use DayNight theme for your app then still not overriden colors will be same as in "light" theme

Related

How do I force apply a dark theme on Android?

According to the docs, I only need to set android:forceDarkAllowed=true in my activity manifest and inherit theme from parent="Theme.MaterialComponents.DayNight". I tried that, but it didn't work.
Here's my manifest file:
<application
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">
<activity
android:name=".MainActivity"
android:forceDarkAllowed="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
And here's my styles.xml styles:
<style name="AppTheme" parent="Theme.MaterialComponents.Light">
...
</style>
<style name="AppTheme.Dark" parent="Theme.MaterialComponents.DayNight">
...
</style>
I tried to get the theme name of the activity by using this code below:
resources.getResourceName(
packageManager.getPackageInfo(packageName, PackageManager.GET_META_DATA)
.applicationInfo.theme
)
It shows me com.example.name:style/AppTheme and not AppTheme.Dark. How can I make it so that when I run the application, the MainActivity automatically sets itself to use AppTheme.Dark (i.e. dark mode) using android:forceDarkAllowed?
That is not how dark mode works on Android 10.
First, Android does not magically append .Dark to your theme at any point, regardless of whether or not the user enabled dark mode. You have android:theme="#style/AppTheme". So, Android will use AppTheme all the time, and your AppTheme.Dark will not be used.
Second, the idea behind DayNight is that you use that as you base theme all the time, and Android will switch between normal and dark modes based on user request. So, if you switch AppTheme to extend DayNight, and get rid of AppTheme.Dark, you will be matching what the documentation calls for.
android:forceDarkAllowed is for cases where you are not in position to use a DayNight theme, and you want Android to try to automatically convert your UI to a dark theme. If you wanted to keep AppTheme extending Light instead of DayNight, this might work (I personally have not tried it with a MaterialComponents theme). But, even then, it will only be when the user has enabled dark mode (e.g., tapped on the notification shade tile).
For example, in this sample app, I use DayNight for my theme:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
</resources>
I have different definitions for those colors in res/values/ and res/values-night/. I do not use forceDarkAllowed. And, when the user toggles night mode, my UI goes from:
to:
How can I make it so that when I run the application, the MainActivity automatically sets itself to use AppTheme.Dark (i.e. dark mode) using android:forceDarkAllowed?
You don't.
If you want a dark theme all the time, use a regular theme (not Light, not DayNight).
If your app uses a dark theme (such as Theme.Material), Force Dark will NOT be applied. Similarly, if your app's theme inherits from a DayNight theme, Force Dark will NOT be applied, due to the automatic theme switching.
Dark theme is available in Android 10 (API level 29) and higher. Make sure that your device's API level is 29 + that your target SDK in the gradle is 29.
There are two ways to apply dark theme:
DayNight - custom-able theme - you control how dark/light theme will look like
Force dark - you control the light theme, and if the user chooses dark mode the system will convert your views to dark theme at runtime.
There are settings to allow dynamically setting day or night regardless of the current system setting.
Each of the options map directly to one of the AppCompat.DayNight
modes:
Light - MODE_NIGHT_NO
Dark - MODE_NIGHT_YES
System default - MODE_NIGHT_FOLLOW_SYSTEM
To switch the theme, call AppCompatDelegate.setDefaultNightMode().
https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#change-themes
This would apply to setting a DayNight theme. If you are trying to take advantage of the Force Dark in Android 10, it applies to the .Light sub-themes. It will not be applied to any of the DayNight or inherently dark themes.
Apps must opt-in to Force Dark by setting
android:forceDarkAllowed="true" in the activity's theme. This
attribute is set on all of the system and AndroidX provided light
themes, such as Theme.Material.Light.
https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#force-dark
Below that, the documentation also specifies how to exclude certain items, either in resources or code.
Force Dark can be controlled on specific views with the
android:forceDarkAllowed layout attribute or with
setForceDarkAllowed().
Beyond that, there are ways to detect the current system light / dark setting and respond to it using the options above, but that is for another post.
It's not a great solution for a dark theme and I apologize for any overlap with the accepted answer, but I do not agree with claiming something isn't possible because it isn't preferred.

Android: How to switch theme for dark mode?

Since Android 10, you can switch between dark mode and default light mode. I didn't make any closer research yet on this since it's a new topic. Is Dark mode color switching automatic by OS or is there any way to tell my App to switch different app-theme if Dark mode is turned on? Also dark mode is possibility for some Android 9 devices.
Because I made custom Dark theme with custom parameters and I set dark color for each of my color in resources (using custom attributes in attrs.xml and applied specific color resource to them inside theme in styles.xml). Same it is working for different color schemes of my App (blue, red, green for example). That way I can tell which color would be used for different views in my App and not system.
Only thing I need is to detect if dark mode is on/off in system. I can force user to turn on Dark mode in App settings (custom settings) but theme can be affected by system dark mode (turned on in Phone settings).
From official documentations:
In order to support Dark theme, you must set your app's theme (usually found in res/values/styles.xml) to inherit from a DayNight theme:
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
You can also use MaterialComponents' dark theming:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
This ties the app's main theme to the system-controlled night mode flags and gives the app a default Dark theme (when it is enabled).
It means that if you use a DayNight theme, the OS itself handles the app theme. if you want to force app uses dark theme check this documentation.
UPDATE:
To detect the device theme:
switch (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
case Configuration.UI_MODE_NIGHT_YES:
…
break;
case Configuration.UI_MODE_NIGHT_NO:
…
break;
}

Dark theme configuration change in Android Q

I want to implement android 10 dark theme in my app , I have these following cases:
SYSTEM_DEFAULT, NIGHT_MODE, LIGHT_MODE
The problem is when I change theme from night or light to system_default from inside the app and it can not understand whether the system is in light mode or dark mode. so the theme won't be updated.
I've tried the dark theme by google
https://developer.android.com/guide/topics/ui/look-and-feel/darktheme
and implementing the configuration still won't be good for me because I don't want to recreate my activity if user changes day to system default when system default is day.
Is there anyway I could handle this?
when(id) {
NIGHT - > theme = Theme.NIGHT_MODE
DAY - > theme = Theme.LIGHT_MODE
SYSTEM_DEFAULT - > theme = Theme.SYSTEM_DEFAULT
}
context ? .clearCachedDrawables()
activity ? .recreate()
}
EDIT:
when (themeStatus) {
Theme.LIGHT_MODE ->
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
Theme.NIGHT_MODE ->
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
Theme.SYSTEM_DEFAULT ->
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
You don't need to set the theme in your activity and recreate it. It's done automatically if you've setup your app theme right.
To use the Dark in your app, you should extend the DayNight theme as your app theme.
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
or
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
If you want for example a different color during dark mode, you should create a 'Android resource directory' called values-night with a 'resource file called colors.xml
In the colors.xml you can set a different color hex for one of your existing colors.
For example:
values/colors.xml contains
<color name="myColor">#000000</color>
values-night/colors.xml contains
<color name="myColor">#FFFFFF</color>
EDIT
You can switch between Dark/light mode in app by calling
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
or
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
or
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)

Select splash screen image and background color based on the application theme not the system(ignore MODE_NIGHT_FOLLOW_SYSTEM.)

I'm using DayNight theme for my android application, and I've made a values-night directory to customize my theme the way I want to, everything is working well, the problem is when I launch my application the splash screen color is chosen depending on the system theme.
let's say the system theme is light and my application is on the dark theme when launch my application the splash screen will be light them colors then the rest of the application will be in the dark theme, and if we change the application theme to light and the system theme to dark then when I launch my application the splash screen will be in the dark theme colors but the rest of the app will be in light theme.
I looked around and I found out that dayNight theme gets the default value for the application theme from the system theme, as you can read in the setDefaultNightMode descriptions
Sets the default night mode. This is used across all activities/dialogs but can be overridden locally via setLocalNightMode(int).
This method only takes effect for those situations where applyDayNight() works. Defaults to MODE_NIGHT_FOLLOW_SYSTEM.
This only takes effect for components which are created after the call. Any components which are already open will not be updated.
I was wondering if there is a way to change that default value? or change the source of the default value.

Set theme programatically to Android system preview window

I have an app in which the user can choose between the default theme and a dark theme. The manifest applies AppTheme to the <application>, while each activity checks the relevant flag and uses setTheme(AppTheme.Dark) if necessary.
This implementation works well for all my activities, but the preview window shown by the OS before the application launches uses the Manifest theme, i.e. the light one. So users get a sudden white screen before reaching the dark app.
Based on other SO answers, I gathered that the only customization we can do is to set a windowBackground drawable for the window to use (and a statusBarColor if needed).
Even though I have two different windowBackground set for each theme, I can't change the theme for the preview window since the Application class seems to load after it, and setting theme there makes no difference.
I'd like to avoid disabling the preview since it adds a noticeable delay without much indication that the app is launching. Is there any solution to this? I'm considering having a dark color for both themes in the worst case, like the Reddit app does.
Styles:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- primary and accent color attributes -->
<item name="android:windowBackground">#color/activityBackgroundLight</item>
</style>
<style name="AppTheme.Dark" parent="AppTheme">
<!-- primary and accent color attributes -->
<item name="android:windowBackground">#color/activityBackgroundDark</item>
</style>
Note: While I'm using colors here, I've already tried with a gradient drawable and it doesn't change anything.
UPDATE: I wasn't able to get any other method, so I went ahead and applied the dark theme by default on the SplashActivity. This means the preview window is always dark, while the check in the SplashActivity's onCreate is inverted (compared to other activities) and applies the light theme if needed.
Still looking for a solution that actually lets me switch at runtime.

Categories

Resources