How do I force apply a dark theme on Android? - 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.

Related

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

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

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.

Support both light and dark theme in Android Pie

Android Pie added the ability to toggle light/dark theme in the Settings -> Display -> Device Theme menu.
I want my app to apply the correct theme according to the Device Theme set in the device settings.
According to the Styles and Themes Android guide, for dark mode the app should use a theme that extends Theme.AppCompat, and for light mode the app should use a theme that extends Theme.AppCompat.Light.
So I created two themes in my app:
<style name="AppTheme.Dark" parent="Theme.AppCompat">
...
</style>
<style name="AppTheme.Light" parent="Theme.AppCompat.Light">
...
</style>
However in AndroidManifest.xml when I declare the application with the <application> tag I can only specify one theme in the android:theme attribute:
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="#style/AppTheme.Light"
tools:replace="android:name">
How do I declare my application in AndroidManifest.xml to dynamically pick #style/AppTheme.Light or #style/AppTheme.Dark according to the Device Theme set in the device settings?
If you want to change theme of an already existing activity, call recreate() after setTheme().
Note: don't call recreate if you change theme in onCreate(), to avoid infinite loop.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Call setTheme before creation of any(!) View.
setTheme(android.R.style.Theme_Dark);
// ...
setContentView(R.layout.main);
}
You may want to try Theme.AppCompat.DayNight instead of defining two themes. Its implementation in this video Cost of a Pixel Color.
However, when I test this on an emulator, toggling Settings -> Display -> Device Theme menu doesn't work. I have to toggle Developer Options -> Night Mode -> Always On and dark theme is picked automatically.
Since I don't own an Android Pie device, I'm not sure if this is a bug of emulator.

Changing background color in a activity.

I used Android Studio to create basic activity using New -> Activity -> Basic Activity. But the activity background colour is black. I know it is to reduce battery consumption. But is there a way to change it to white colour, without changing style.
I tried to change the background colour of the root layout, but then it won't show hint text of edit text field. Because it's colour is white.
Then I tried to change theme from Material to Material Lite, then it wouldn't show the change when I run the app in the device.
Here is the activity declaration in AndroidManifest.xml
<activity
android:name=".SearchBus"
android:label="#string/title_activity_search_bus"
android:parentActivityName=".MapsActivity"
>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="uk.co.stableweb.iroute.MapsActivity" />
</activity>
In your styles.xml set the android:windowBackground attribute for whatever theme you are using for application or activity. You can find the theme you are using in your AndroidManifest.xml.
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:windowBackground">#color/somecolor</item>
</style>
</resources>
Note: If you have views in your layout that aren't transparent, it will block you from seeing the color you set here.
Did you try :android:background="#ffffff" i? It works for me

Android application Theme overriding view theme

I have been developing an Android app for quite some time now and almost everything is how it's supposed to be. However, I'm having some issues with themes for some views. My application uses a AppCompat.Light based theme as shown bellow:
<style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar"></style>
Everything looks white and clean, but I have one specific screen that is kind dark. So I created the following theme for some EditText fields:
<style name="InputField" parent="Theme.AppCompat"></style>
in order to make the input fields have white colors. I then run the application on devices with different Android versions. On a smartphone with Android 5.0.2, everything looks as I expected. On a smartphone with android 4.4.4, however, the input is dark. I even tried to change the theme of the input field theme to
<style name="InputField" parent="Theme.Holo"></style>
or
<style name="InputField" parent="#android:style/Widget.Holo.EditText"></style>
in the values-v19 styles, but it still looks dark. If I change the application theme to
<style name="AppBaseTheme" parent="Theme.AppCompat.NoActionBar"></style>
the input fields look as they should, but the entire rest of the app is dark themed and it's not what I want. I can only assume that application theme is having some influence over my views theme, even though I explicitly specified the theme they should use. The same behavior happens on a smartphone with android 4.2.2.
System provided styles doesn't define used colors, they have only references to a theme attributes. Colors are defined the theme, thus, it not enough, if you set parent to some system style.
Starting API 21 (5.0) you can override theme for specific views (or styles) by setting attribute android:theme. For older versions you will need to define specific colors and drawables in your style.

Categories

Resources