Android default theme - android

I am making one android application but i was thinking about themes..
If i don't declare a theme of my Android application which theme will be used?
Where i can find this information?
What is the criteria for use one and other?
I was thinking about, if i want customize my all application, i have to extend one theme and custom all item that i want to customize.
And what if it assumes one of them as default? Weather I have to customize it again? How do i know what is the default one?

The default theme varies depending on the API level (to be consistent with the general UI).
On API < 10, the theme was a set of styles (as in the link below) known as Theme, above that API 10, the default theme was Theme_Holo and now, starting with API 21, the default theme has become Theme.Material.
API < 10: see the frameworks's code Theme or Theme.AppCompat
10 >= API < 21: read the Styles and Themes guide Holo_Theme or Theme.AppCompat
API >= 21 Using the Material Theme guide Theme.Material
Most of those styles are available through the android.support libraries.
PS: AFAIK the light theme has always been the default one.

It is best to define a default theme yourself instead of relying on android to pick the default theme. This is because different versions of android may have completely different default themes, and could mess up your layouts.
You can declare a theme for your application in AndroidManifest.xml
<application android:theme="#style/MyTheme" .....>
Then in res/values folder, you edit/add a file themes.xml and add something like the following:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="MyTheme" parent="#android:style/Theme.Holo">
... customize your theme here
</style>
</resources>
You can edit the parent of your theme to anything you want...
You can also use #android:style/Theme.Holo directly in AndroidManifest.xml if you do not want any customization at all.
Use Theme.AppCompat.Holo if API version below 11

The default theme for App is implement in Resources.java!
/**
* Returns the most appropriate default theme for the specified target SDK version.
* <ul>
* <li>Below API 11: Gingerbread
* <li>APIs 11 thru 14: Holo
* <li>APIs 14 thru XX: Device default dark
* <li>API XX and above: Device default light with dark action bar
* </ul>
*
* #param curTheme The current theme, or 0 if not specified.
* #param targetSdkVersion The target SDK version.
* #return A theme resource identifier
* #hide
*/
public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
return selectSystemTheme(curTheme, targetSdkVersion,
com.android.internal.R.style.Theme,
com.android.internal.R.style.Theme_Holo,
com.android.internal.R.style.Theme_DeviceDefault,
com.android.internal.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
/** #hide */
public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo,
int dark, int deviceDefault) {
if (curTheme != 0) {
return curTheme;
}
if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {
return orig;
}
if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return holo;
}
if (targetSdkVersion < Build.VERSION_CODES.CUR_DEVELOPMENT) {
return dark;
}
return deviceDefault;
}
It varies depending on the API level, so you'd better to define your own AppTheme in AndroidManifest.xml to assure Theme in all API level devices.
Pls refer previous answer.

Related

Application of the system theme

Starting with Android 10, it became possible to change the device theme from settings (to dark and light), and the application by default grasps the theme that is set in the system. But I ran into a rather interesting problem. A device with Android 9 and in the settings there is also the possibility of changing the theme, but when I use a dark theme, nothing happens and my application remains in the light theme. I read on the Internet and found a way to get a theme(is light):
private fun foo(): Boolean {
return resources.configuration.uiMode and
Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_NO
}
, but this function always returns that a light theme has been applied (in Android 9 when a dark theme is enabled in the settings). As far as I understood, this is because this function returns the theme that is in the application and wanted to find out how, in this case, you can get the theme of the system.
The resources associated with the Activity will reflect the configuration of that Activity. That means that resources.configuration (or any context.resources.configuration) will have the uiMode of your Activity, not of the System.
When your application is starting, Android must create the Application instance for your app. At this moment your resources are not loaded yet, so Android attaches resources and configuration of the System to your Application instance. So you can access the uiMode of the System from the application Context. Also, you can access System resources and configuration using Resources.getSystem(), which is handy when you don't have access to any Context.
val activityIsLight =
resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_NO
val systemIsLight =
applicationContext.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_NO
// Or without using any Context
val systemIsLight =
Resources.getSystem().configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_NO

How can I detect programmatically if the Android Device is in Dark Mode?

I'm trying to support the Android Q Dark theme for my Android app and I can't figure out how to import different assets based on the theme I'm currently in.
Im using the official DayNight theme for making the dark/light versions and for drawables is very easy to just point to the XML and it will choose the correct value either from values or values-night depending on what is enabled.
I wanted to do something similar where depending on the theme it would load either the asset "priceTag_light.png" or "priceTag_dark.png".
val inputStream = if(darkIsEnabled) {
assets.open("priceTag_dark.png")
} else {
assets.open("priceTag_light.png")
}
Is there a way I get that flag?
Okay finally found the solution I was looking for. As #deepak-s-gavkar points out the parameter that gives us that information is on the Configuration. So, after a small search I found this article that gives this example method that has worked perfectly for what I wanted:
fun isDarkTheme(activity: Activity): Boolean {
return activity.resources.configuration.uiMode and
Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
}
You first need to do this changes in manifest
<activity
android:name=".MyActivity"
android:configChanges="uiMode" />
then onConfigurationChanged of activity
val currentNightMode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
when (currentNightMode) {
Configuration.UI_MODE_NIGHT_NO -> {} // Night mode is not active, we're using the light theme
Configuration.UI_MODE_NIGHT_YES -> {} // Night mode is active, we're using dark theme
}
Use the following code:
boolean isDarkThemeOn = (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;

AppCompat DayNight theme not work on Android 6.0?

I am using the new Theme.AppCompat.DayNight added in Android Support Library 23.2
On Android 5.1 it works well.
On Android 6.0, activity looks like using light theme, but dialog looks using dark theme.
My Application class:
public class MyApplication extends Application {
static {
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_YES);
}
}
My styles.xml
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
<style name="Dialog.Alert" parent="Theme.AppCompat.DayNight.Dialog.Alert"/>
My code to show a dialog:
new AlertDialog.Builder(mContext, R.style.Dialog_Alert)
.setTitle("Title")
.setMessage("Message")
.show();
Google have fix it in support 23.2.1
Old answer:
On Android 6.0, system's night mode setting defalut is UiModeManager.MODE_NIGHT_NO, it will change Resources.Configuration.uiMode before onCreate is called. However, support library apply its night mode setting in onCreate in AppCompatActivity, it's too late, I think thats why it not work on 6.0.
So if we can Override getResources() in AppCompatActivity and change uiMode.
Old answer:
Here are code to fix not work on Android 6.0
public class Application extends android.app.Application {
static {
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_);
}
#Override
public void onCreate() {
super.onCreate();
// add this code for 6.0
// DO NOT DO THIS. It will trigger a system wide night mode.
// This is the old answer. Just update appcompat.
// UiModeManager uiManager = (UiModeManager) getSystemService(Context.UI_MODE_SERVICE);
// uiManager.setNightMode(UiModeManager.MODE_NIGHT_);
}
}
Note: If your app don't have location permission, your app will not have the same calculate result of system. It means it is possible support library thinks it is night now when system not, this will cause some of your UI looks dark some light.
The best way is wait for Google to fix it.
The best solution is to update context with proper config. Here is a snippet of what I do:
public Context setupTheme(Context context) {
Resources res = context.getResources();
int mode = res.getConfiguration().uiMode;
switch (getTheme(context)) {
case DARK:
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
mode = Configuration.UI_MODE_NIGHT_YES;
break;
case LIGHT:
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
mode = Configuration.UI_MODE_NIGHT_NO;
break;
default:
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);
break;
}
Configuration config = new Configuration(res.getConfiguration());
config.uiMode = mode;
if (Build.VERSION.SDK_INT >= 17) {
context = context.createConfigurationContext(config);
} else {
res.updateConfiguration(config, res.getDisplayMetrics());
}
return context;
}
Then use the context in your Application like so
#Override
protected void attachBaseContext(Context base) {
Context context = ThemePicker.getInstance().setupTheme(base);
super.attachBaseContext(context);
}
Add getDelegate().applyDayNight(); after setDefaultNightMode.
This issue was reported on https://code.google.com/p/android/issues/detail?id=201910
But after release of Android Support Library, revision 23.2.1 (March 2016). This issue has been resolved.
Fixed a compatibility issue with Night Mode and API level 23
update Support Library to Android Support Library to 23.2.1
As of now, no Gradle dependency is needed to enable the night mode other than androidx.appcompat:appcompat:1.0.2 which will already be present. Make sure to change the default theme from Theme.AppCompat.Light.DarkActionBar to Theme.AppCompat.DayNight.DarkActionBar in the styles.xml file and then do AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) to switch to the night mode. I have tested it in APIv23(Android 6.0) and above and it is working fine.
For a better explanation see this codelab by Android
just add this in your values-v21
<style name="Theme.AppCompat.DayNight">
work for me
done.

making customized theme for android phone

I'm a new mobile developer and i know how to put theme on an application i was able to make 2 mobile application as of now but i wanted to try to make a customized theme for phones. I'm wondering if anyone out there has idea on the following.
1.how to make a customized theme for phone.
2.what is the format of the theme.
3.is it possible to make it in eclipse.
4.what are the things needed to consider to make a theme for phone.
5.how to implement customized theme on phone.
6.available tutorial on making a customized phone theme.
If you want to change theme of a specific theme application like GO Launcher or aHome you can find a link on their site, see this question for more information Themes in Android?
but you can also write your launcher application, if you want to do this, you can see this links: Build An Application Launcher For Android
But if you want to change theme of your application, so you can read these documents and tutorials:
developer.android.com/guide/topics/ui/themes.html
Android Styles and Themes - Tutorial
Another way that i think you must know for building several themes is building an apk for every theme of your application, this solution make your app size smaller. like this function:
public static Resources getResource() {
resourcePackageName = "com.mine.MyApp";
PackageManager packageManager = mContext.getPackageManager();
Resources resources = null, resources2 = null;
try {
resources = mContext.getResources();
resources2 = packageManager
.getResourcesForApplication("com.mine.MyAppTheme");
resourcePackageName = "com.mine.MyAppTheme";
} catch (Exception e) {
Log.d("ss", e.toString());
}
if (resources2 != null)
mResource = resources2;
else
mResource = resources;
return mResource;
}
In this code, your app name is com.mine.MyApp and you have a app with all of resources in the com.mine.MyApp that is your theme, name of theme apk app is com.mine.MyAppTheme. you can use several apk as several theme. just put your resources on theme apk file. you can see this question:
Writing themed applications in Android

build for different targets conditionally

I have been building for API 14 so far. I'm trying to get ready now, so I downloaded and specified API 7 as my target. I have some compilation errors because a few api's I was using in API14 aren't available in API7.
I am wondering how I could put them in conditionals. Something on the lines of:
if (API_14)
{
if (mTextEdit.isEmpty()) {
// Do Something
}
} else if (API_7){
if (mTextEdit.matches("")) {
// Do the same thing
}
}
This has to be a compile time conditional switch because otherwise my code won't even compile.
I've heard before that pre-processors are not supported in Java, so I welcome suggestions on how best to manage my source which I'm targeting for multiple versions.
Edit:
I also am running into trouble with my state list drawable:
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:state_pressed="true"
android:drawable="#android:color/holo_orange_dark" />
<item android:drawable="#android:color/transparent" />
</selector>
Of course, hold_orange_dark isn't available in API7. I'd like to be able to manage those as well.
You can't do ifs, or you'll have a crash on older devices.
You have to use Java Reflection to use methods from more recent APIs conditionally.
An example: http://mobile.tutsplus.com/tutorials/android/java-reflection/
For your resources you can specify different directories for different platform versions. So you'd make a Values-v14 directory to have a copy of any resources that use anything from that API version and a Values directory so Values would be used by default and Values-v14 would only be used if the device was version 14.
As for doing it programmatically, you could try a Try-Catch like so-
try {
//Insert ICS stuff here
} catch(NoSuchMethodError e){
}
Or you could try this-
public static boolean isHoneycomb() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
}

Categories

Resources