where are android style item attributes defined? - android

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="colorWindowBackground">#color/Gray</item>
</style>
I wanted to add the property colorWindowBackground like so. Can I not just use any name I like? it seems like Android studio does not appreciate my behavior.
I'm guessing then that colorPrimary from item name is defined somewhere already. and that name can only be set to certain already existing properties.
how does the compiler know which properties are allowed? Is it somehow based on the parent the style is inherited from?

For using custom attributes in the views of layouts, you can use "declare-stylable" for custom names. Please follow below referred site :
https://guides.codepath.com/android/Defining-Custom-Views

#james Joshua, colorPrimary, colorAccent, and colorPrimaryDark are defined or in other words inherited from parent style Theme.AppCompat.Light.DarkActionBar.

Related

Why and when we need to add android: prefix to style?

I have seen that some Style attributes require android prefix and some don't need it. What is the reason. like
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
Why we haven't use android:windowActionBar and android:windowNoTitle
Based on SDK version Android styles are grouped in different namespaces. In order to override a Theme you have to follow it's namespace.
That's the reason you don't need the android: prefix when extending an AppCompat Theme, but if you wanted something else, let's say Theme.Holo - you'd have 2 different styles for the them - one for pre-Lollipop devices, and one for -21, the latter having the android: prefix before each style attribute.
It depends on which Themes you're using and which context it is. These attributes are defined by different sources.
If the attribute name is prefixed with android:, it's a framework attribute and can only be used for the Android versions having it defined.
If the attribute is not prefixed at all, the attributes are defined by your own application. This includes all attribute definitions you pulled in with libraries.
In your example you're defining a theme for AppCompat which is part of the support library and thus of your application. The framework widgets won't recognize these colors directly.

Overriding the theme attribute inside of a style?

I have a project where I defined all the styles in the theme (Button style, Checkbox Style, EditText style and so on) This way I don't need to apply any style or theme in the layouts where I use those views, because they are applied automatically by my AppTheme.
Now I encountered a problem. I wanted to define the Switch style inside the theme but it should use another color for the colorControlActivated and colorControlHighlight. By default it uses the colorPrimary which I defined in the theme, but what if I want to change that.
The problem can be fixed easy with a theme overlay or a style where I override the needed attributes that I mentioned above and apply that style/theme everywhere where I use the Swtch view. But I want to know if I can avoid that and define a default style for my Switch views inside the same theme where the colorControlActivated and colorControlHighlight are already defined.
I tried several things but this looked like the one that actually might work but it does not:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorControlActivated">#color/colorPrimary</item>
<item name="colorControlHighlight">#color/colorPrimary</item>
<item name="colorSwitchThumbNormal">#color/white</item>
<item name="switchStyle">#style/SwitchStyle</item>
</style>
<style name="AppTheme.GreenControlOverlay">
<item name="colorControlActivated">#color/green</item>
<item name="colorControlHighlight">#color/green</item>
</style>
the SwitchStyle looks like this
<style name="SwitchStyle" parent="Widget.AppCompat.CompoundButton.Switch">
<item name="android:theme">#style/AppTheme.GreenControlOverlay</item>
</style>
I dont know why this is not working because if I set the android:theme inside my AppTheme directly it does override the colorControl attributes, but if you override it from a style it does not work. If I apply this GreenControlOverlay on the Switch view inside of my layout it also works.
Is it even possible to do this?
If you have any questions please don't hesitate to ask. I hope I explained my problem well.

what is ColorPrimaryLight and how do I use it?

I get this as one of my colors generated by the Material Design Color Platte.
But in this image:
I don't see colorPrimaryLight anywhere. What is it used for and how do I declare it? Do declare it like this in my style?:
<item name="colorPrimaryLight">#color/colorPrimaryLight</item>
Or do I declare it in a different way? And what is it used for?
By default, the statusBarColor is set to colorPrimaryDark. If you want to use colorPrimaryLight for the status bar you need to set android:statusBarColor to android:colorPrimaryLight.
https://developer.android.com/training/material/theme.html
in your resources file put:
<color name="colorPrimaryLight">#D1C4E9</color>
in your styles file put:
<item name="colorPrimaryLight">#color/colorPrimaryLight</item>
TL;DR: colorPrimaryLight is one of several colors identified as part of the Material palette that is not actually mapped to a Theme attribute in Android. The guidelines recommend using it in several areas such as a TabLayout backgrounds.
I cannot find an authoritative source about using this attribute in Android apps, but it seems that Material defines a large number of colors, as shown on this helpful page, but not all of them are mapped to Android Theme attributes. For instance, if you create a brand new single-Activity project in Android Studio and modify styles.xml as shown below:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<!-- THIS THEME ATTRIBUTE IS NOT FOUND -->
<item name="colorPrimaryLight">#color/colorPrimary</item>
</style>
</resources>
The colorPrimaryLight attribute is not found by the compiler.
Therefore if you wanted to use it in your application you would presumably have to explicitly link to a color.xml resource. This seems to negate the benefit of the Theme system somewhat, but perhaps I am missing a trick.

Is this the correct way to have different values/styles for different versions

Android Studio 2.1 preview 3
This is just a question, as I am confused as I have seen many alternatives in doing this.
I have created a new android project and my Activity extends AppCompatActivity
public class MainActivity extends AppCompatActivity {
I want to have the transparent statusbar on devices running 21 and over.
So in my values/styles I have the following
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.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 my values-21/styles I have the following
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<!-- Make the statusbar transparent -->
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>
My Manifest I select the theme
android:theme="#style/AppTheme"
Just some questions
Is this the correct way, or is there any better way to do this?
Would values-21/styles inherit all the colors in values/styles so I would have to repeat this?
It's the right way. May I suggest you to organize your style better?
values/styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="CommonTheme">
</style>
<style name="CommonTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
</resources>
values-v21/styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="CommonTheme">
<!-- All customization of the theme for this version -->
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>
So you don't need to repeat the common values of the style for every api level.
I will try to answer it giving some references
Maintaining Compatibility
To avoid duplication of code, define your styles inside res/values/,
modify the styles in res/values-v21/ for the new APIs, and use style
inheritance, defining base styles in res/values/ and inheriting from
those in res/values-v21/
So you should try to avoid code duplication in your style.xml at different folders res/values/ and res/values-v21/ by using style inheritance.
Style Inheritence
If you want to inherit from styles that you've defined yourself, you
do not have to use the parent attribute. Instead, just prefix the name
of the style you want to inherit to the name of your new style,
separated by a period.
If you want to inherit a style that you've defined yourself you can skip adding a parent attribute and inherit from it using a dot or period notation.
With this, you can define a base theme BaseTheme in res/values/ with different colors and inherit from it as BaseTheme.StyledStatusBar without specifying a parent attribute.
<resources>
<style name="BaseTheme.StyledStatusBar"></style>
<!-- Base application theme. -->
<style name="BaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
</resources>
In values-21/, add item android:windowTranslucentStatus to BaseTheme.StyledStatusBar
<resources>
<style name="BaseTheme.StyledStatusBar">
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>
In manifest, select the theme
android:theme="#style/BaseTheme.StyledStatusBar"
1) Is this the correct way, or is there any better way to do this?
Yes. That's the correct/recommended way of having different values for different API versions.
2) Would values21/styles inherit all the colors in values/styles so I would have to repeat this?
I'm not sure I fully follow this question. Both styles you showed will inherit from Theme.AppCompat.Light.NoActionBar so your colors should be declared again, but I'll present two better alternatives:
Alternative 1, a little bit better:
Use a BaseTheme that is common for both. To view the code for it, please check #mimmo-grottoli answer.
Alternative 2, much better:
If the only different on the two themes is the android:windowTranslucentStatus that was introduced in KitKat (API level 19), you can put it all in the same theme in values/styles, like the following:
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<!-- Make the statusbar transparent -->
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>
The Android Framework ignores XML parameters that it does not recognize. That means that on JellyBean or ICS, the device will ignore windowTranslucentStatus while correctly applying the colors and in KitKat and up, it will correctly apply windowTranslucentStatus.
That tricky is valid for all XML in Android (even layouts), the IDE might give you warnings about API level, but in XML they're always safe to use.
Different folders of values/styles are made to give a unique style when your app is running on a specific version of Android.
So yes you are right when saying that the newer version inherits from the older one. When adding items in your latest version of styles you keep the latest version up to date to the latest APIs.
To conclude, your way is the very commun way, it's an organized and a clean way to keep your app updated.
Is this the correct way, or is there any better way to do this?
Yes. That's the right way of having different values for different API versions.
Would values-21/styles inherit all the colors in values/styles so I would have to repeat this?
Yes
technically <item name="android:windowTranslucentStatus">true</item> won't give you fully transparent statusbar.
If you want it to by fully transparent, you can use <item name="android:statusBarColor">#android:color/transparent</item>

Styling the popup menu in Android 5.0

I'm making my app ready for Android 5.0, I'm using the latest compatibility library, here is what my style looks like.
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/theme_accent</item>
<item name="colorAccent">#color/theme_accent_secondary</item>
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
<item name="colorPrimary">#color/theme_accent</item>
<item name="colorAccent">#color/theme_accent_secondary</item>
</style>
</resources>
(The ActionBar color is being set programmatically.)
Now, I want the overflow/popup menu to have the dark background like it had in the holo implementation, but I can't get it to work, here is what it looks like:
I have tried setting the popupMenuStyle but it didn't work.
How can I make the popup menu darker?
Stop using the ActionBar. If you want a ToolBar to be set up like an ActionBar, follow this guide on the android-developers blog.
It actually mentions your use case at Dark Action Bar and provides this code:
<android.support.v7.widget.Toolbar
android:layout_height=”wrap_content”
android:layout_width=”match_parent”
android:minHeight=”#dimen/triple_height_toolbar”
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
Not a full answer but what I found so far:
In past versions you needed to specify a drawable (Check https://github.com/StylingAndroid/StylingActionBar code and tutorials)
Apparently, now that is a color. To modify it you need to do specify the following theme:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
<item name="android:actionBarPopupTheme">#style/popupNew</item>
</style>
<style name="popupNew" parent="android:ThemeOverlay.Material.Light">
<item name="android:colorBackground">#color/red</item>
</style>
</resources>
This works correctly if the theme applied to the app is just this.
If I add android:actionBarPopupTheme to my existing theme, it doesn't work. I am trying to figure out why.
Solved my problem by using this style:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/theme_accent</item>
<item name="colorAccent">#color/theme_accent_secondary</item>
<item name="actionBarStyle">#style/AbStyle</item>
<item name="actionModeBackground">#color/actionmode_bg</item>
</style>
<style name="AbStyle" parent="Widget.AppCompat.Toolbar">
<item name="elevation">2dp</item>
<item name="displayOptions">homeAsUp|showTitle</item>
<!--showHome-->
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
<item name="colorAccent">#color/theme_accent_secondary</item>
<item name="actionBarStyle">#style/AbStyle</item>
</style>
I had to use Widget.AppCompat.Toolbar as the parent actionBarStyle
Add the property popupTheme to your toolbar:
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/color_primary"
app:theme="#style/Theme.AppCompat.Light"
app:popupTheme="#style/Theme.AppCompat" />
Or define a new style for your toolbar:
<style name="MyToolBarStyle" parent="Widget.AppCompat.Toolbar">
<item name="android:background">#color/green</item>
<item name="popupTheme">#style/Theme.AppCompat.Light</item>
<item name="theme">#style/Theme.AppCompat</item>
</style>
This question has already been answered for styling via XML, but I'm adding an explanation here of how to work out the solution to this and similar styling questions yourself.
First, this is the solution when using AppCompat. To your App's style.xml add actionBarPopupTheme to your theme:
<style name="Theme.MyTheme" parent="#style/Base.Theme.AppCompat.Light.DarkActionBar">
...other stuff here
<item name="actionBarPopupTheme">#style/Theme.MyTheme.ActionBarPopupTheme</item>
</style>
<style name="Theme.MyTheme.ActionBarPopupTheme" parent="#style/ThemeOverlay.AppCompat.Light">
<item name="android:textColor">#android:color/white</item>
<item name="android:background">#android:color/black</item>
</style>
Here's the steps I took to arrive at this solution (it takes a bit of detective work as the Android documentation is poor):
Open your App's style.xml in Android Studio
On the line where you App's theme is defined, put your screen cursor in the parent theme (e.g. click in #style/Base.Theme.AppCompat.Light.DarkActionBar) then press F4. This should take you to the source code for the style in the appcompat library.
Within this style I saw this line:
< item name="actionBarPopupTheme">#style/ThemeOverlay.AppCompat.Light< /item>
This looked like a possible place to change the theme of the popup. I searched for "actionBarPopupTheme" in the poor
Android developers documentation and found "Reference to a theme that should be used to
inflate popups shown by widgets in the action bar". So this was worth playing with.
I copied the appcompat line containing "actionBarPopupTheme" to my style.xml then in this line replaced the item's theme reference (the bit in bold above) with Theme.MyTheme.ActionBarPopupTheme.
In my style.xml I created my new style named Theme.MyTheme.ActionBarPopupTheme. I used the same parent that was used in the style I copied from the appcompat source (the bit in bold above).
To ensure my new popup style was working, I changed the parent style to ThemeOverlay.AppCompat.Dark then ran and tested the code on a device. The popup style changed, so now I knew my overriding of actionBarPopupTheme was the correct thing to do. Then I changed back to ThemeOverlay.AppCompat.Light.
The next challenge is to work out what item names to override in Theme.MyTheme.ActionBarPopupTheme. I changed the text and background colours. To find the correct item names that change the style of something can be tricky in some cases. One way to find less obvious style item names is to look through the style definitions in the appcompat xml file (the one you opened when pressing F4 in the 2nd step above), continually descending into parent styles (F4 again!) until you find something that may do what you want. Google searches will help here too.

Categories

Resources