I want to see the definition of divider vertical, I'm not sure exactly what the meaning of an attribute is but when click through to the definition of the attribute in intellij I'm taken to attrs.xml and shown the following, which does not help.
<!-- Drawable to use for generic vertical dividers. -->
<attr name="dividerVertical" format="reference" />
My specific problem is I'm trying to achieve a list with an inset list divider with the dividerVertical style. In order to do this I have defined my own inset shape.
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="30dip"
android:insetRight="30dip">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?android:attr/dividerVertical"/>
</shape>
</inset>
This does not work as android will not accept the "?android:attr/dividerVertical" as the colour. It would not work anyway as divider vertical has an alpha component, so what I need to know is what colour and opacity is divider vertical?? But ideally Id like to know how I can check the source of any resource components in android so that I never encounter this problem again.
Thanks
Piers
According to developer.android, ?[<package_name>:][<resource_type>/]<resource_name> is used for References To Theme Attributes.
So, for ?android:attr/dividerVertical, you can navigate to android-sdk\platforms\android-16\data\res\values. There, looking at attrs.xml, you can see
<!-- Drawable to use for generic vertical dividers. -->
<attr name="dividerVertical" format="reference" />
But this is just a "reference" for the theme. Looking at your target platform's themes.xml, you can find many lines for different themes something like
<item name="dividerVertical">#drawable/divider_vertical_dark</item>
The line you want is the line contained within the theme element for the theme you are using. It's easiest to copy the whole theme element to another text file and search there. Which brings up
<item name="dividerVertical">?android:attr/listDivider</item>
Searching again in the theme for "listDivider" you can find
<item name="listDivider">#drawable/list_divider_holo_dark</item>
So that is a drawable.
Searching for matching files you can find
./platforms/android-16/data/res/drawable-hdpi/list_divider_holo_dark.9.png
./platforms/android-16/data/res/drawable-mdpi/list_divider_holo_dark.9.png
./platforms/android-16/data/res/drawable-xhdpi/list_divider_holo_dark.9.png
These pngs happen to be 9 patches with the content consisting of a white square with an alpha value of 38.
dividerVertical is defined in theme you are using. For example this is divider image for Holo.Light theme. There is <item name="dividerVertical">?android:attr/listDivider</item> row in themes.xml. This line is referencing forward to <item name="listDivider">#drawable/list_divider_holo_light</item>, from this you can see that it is drawable and not a color.
Related
I'm trying to make a simple theme extending from AppCompat and I want to change the background color of a Spinner's pop-up. I can get pretty far in completely restyling AppCompat purely by using colors, but got stuck on the Spinner.
Inspecting the xml for Widget.AppCompat.Spinner, I see that its android:popupBackground is a 9-patch bitmap for API 20 and lower, but a vector drawable for 21 and higher. I know how to create a tinted 9-patch.
For 21+, the spinner background is defined in popup_background_material.xml as:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="2dp" />
<solid
android:color="?attr/colorPopupBackground" />
</shape>
I tried setting this color attribute in my values-v21 style like this:
<style name="MyTheme" parent="MyBaseTheme">
<item name="android:colorPopupBackground">#color/colorSpinnerBackground</item>
</style>
But at build time there is an error:
AAPT: error: style attribute 'android:attr/colorPopupBackground' is private.
Is there some simpler way of recoloring Spinners that I'm missing? I know I could copy-paste the vector xml file and change the color there, but I'd prefer to stick to colors only so if there are changes to AppCompat's theming, I can get them automatically by updating its version.
Currently using AppCompat 1.0.2.
I have a good example about custom spinner.
This example show how to change spinner background color.
but it is korean, not english
see link.
https://blog.naver.com/jinhan38/222094163563
What is best practice to organise styling of buttons of a professional android application? Assume a larger contemporary application (SDK 26+, min SDK 21).
This question is answerable, as both the sources of Material Design and the setup of Android Studio give enough clues and examples of the patterns of the intended professional usage. Surely the user is not limited to this patterns, but following them, makes the application play well together with the sources of Material Design and provides best maintainability.
I find several ingredients related to the styling of buttons.
#style/Widget.AppCompat.Button
#style/Widget.AppCompat.Button.Colored
#style/TextAppearance.AppCompat.Button
#style/TextAppearance.AppCompat.Widget.Button
#color/foreground_material_dark
?colorAccent
?textColorPrimary
?android:colorForeground
?textAppearanceButton
There may be more.
How are all the ingredients related?
How are they intended to be used together in professional theming?
You can look up the sources. However, even knowing all details does not give the full picture of the intended usage. This question is asking to draw the picture.
(Min SDK 21)
General Approach
Granularity
I think it an enough fine-grained approach to separate the text appearance from the backgrounds. This gives the option to combine different backgrounds with different text appearances. It also matches the two style settings provided by Button and the organisation of Material Design. Hence it addresses the question, how it is intended to be used.
The price is, that each Button needs both settings:
Button text: android:textAppearance
Button background: style
To even lower this price styles_material.xml in fact takes an advanced approach. Each button style already includes a default text appearance. So in the normal case I only have to apply the button style.
<Button
style="?defaultButtonStyle"
I follow this pattern for my own button styling, as the question is for the intended usage. If I want to modify the default, I add an alternative text appearance by setting it to android:textAppearance.
<Button
style="?defaultButtonStyle"
android:textAppearance="?smallButtonTextAppearance"
For very special buttons I still can adjust the styling on the level of the layout file. This is the lowest level of granularity.
Hint: Be aware that android:textAppearance has a very low
precedence. If you set a text attribute somewhere in the theme (or style),
you will overwrite the same attribute in all of android:textAppearance.
It works with a similar force like the "!important" annotation in CSS,
which can be a pretty pitfall.
Flexible theming
Without
If I don't plan to use different themes, I can set the styles directly into the layouts.
<Button
style="#style/My.DefaultButtonStyle"
android:textAppearance="#style/My.SmallButtonTextAppearance"
...
With
If a want to be able to exchange themes, I map all types of styles to attributes first. Then I set the styles indirectly by using the attributes. This gives me the option to connect other styles for other themes, without the need to duplicate layouts.
<Button
style="?defaultButtonStyle"
android:textAppearance="?smallButtonTextAppearance"
...
I personally prefer not to use or mix given attributes, but to fully define my own set of attributes addressing my design. So the levels of the onion stay cleanly separated.
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<!-- button text appearance -->
<attr name="defaultButtonTextAppearance" format="reference" />
<attr name="smallButtonTextAppearance" format="reference" />
<!-- button backgrounds -->
<attr name="defaultButtonStyle" format="reference" />
<attr name="alarmButtonStyle" format="reference" />
In the themes the attributes are mapped to theme specific styles.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="OtherTheme" parent="Theme.AppCompat">
<!-- button text appearance -->
<item name="defaultButtonTextAppearance">#style/OtherTheme.DefaultButtonTextAppearance</item>
...
<!-- button backgrounds -->
<item name="defaultButtonStyle">#style/OtherTheme.DefaultButtonStyle</item>
...
Button Text
If I track down the styles to the sources I come to a file data/res/values/styles_material.xml, which defines the root of all button text appearances. TextAppearance.Material.Button inherits from TextAppearance.Material, but the four relevant attributes for buttons are overwritten.
<style name="TextAppearance.Material">
<item name="textColor">?attr/textColorPrimary</item>
<item name="textColorHint">?attr/textColorHint</item>
<item name="textColorHighlight">?attr/textColorHighlight</item>
<item name="textColorLink">?attr/textColorLink</item>
<item name="textSize">#dimen/text_size_body_1_material</item>
<item name="fontFamily">#string/font_family_body_1_material</item>
<item name="lineSpacingMultiplier">#dimen/text_line_spacing_multiplier_material</item>
</style>
<style name="TextAppearance.Material.Button">
<item name="textSize">#dimen/text_size_button_material</item>
<item name="fontFamily">#string/font_family_button_material</item>
<item name="textAllCaps">true</item>
<item name="textColor">?attr/textColorPrimary</item>
</style>
It can be overwritten by my own inherited styles. It also shows, that it would be easy to write my own text appearance style without using inheritance at all.
Color
Understanding Androids text color management system is them most confusing part, because the system is quite powerful. Here comes some enlightenment.
In the above TextAppearance.Material.Button I find text color is specified by the attribute ?textColorPrimary. This attribute again is based on the attribute ?android:colorForeground.
The attribute ?android:colorForeground is the central switch to set the text colors. Be default all text colors are calculated based on this setting, also those of the buttons. For example different grades of greyed-out or opaque variants are calculated for disabled buttons, for body text, etc.
Instead of touching dozens of different places it is a good idea to set the common default text color here and rely on the default Android color calculating system as far as useful. Tweak it in details.
<item name="android:colorForeground">#color/orange_700</item>
This setting defaults to #color/foreground_material_dark.
Hint 1: If you edit the setting by use of
the Android Studio Theme Editor, it will possibly change the
value of#color/foreground_material_dark. To me it does not
feel like a good idea to change a value of material dark because
it is not my realm. Better use a reference like shown before.
Hint 2: The Theme Editor is an appropriate tool to discover
the relations of the color attributes system. This relations reveal,
when you experimentally try to edit the different attributes with the editor.
If I want a button text color that varies from the overall text color, I set it on the level of the text appearance style.
Hint 3: Using ?android:colorForeground does not work out of the
box below API 26. For a workaround see here.
Text size
The text size is the factor of the text appearance, that I typically want to directly adjust to my own design within my customised text appearance styles.
<style name="My.SmallButtonTextAppearance" parent="My.DefaultButtonTextAppearance">
<item name="android:textSize">16sp</item>
</style>
TextAppearance.Material.Button takes the text size default from the resource #dimen/text_size_button_material. There is no system with a central text size setting comparable to the text color setting system.
All caps
The root style TextAppearance.Material.Button set's all caps to true. There is not even a resource, the value is taken from. It's just hard coded.
<item name="textAllCaps">true</item>
There is a high chance, I want to set it to false in my customised button styles.
<item name="android:textAllCaps">false</item>
Font family
As with the text colors the font family typically is a system with a common central nature. How is it managed for the buttons? The root style TextAppearance.Material.Button makes use a the string resource #string/font_family_button_material.
<item name="fontFamily">#string/font_family_button_material</item>
In the file data/res/values/donttranslate_material.xml this is set to sans-serif-medium, while in the file data/res/values-watch/donttranslate_material.xml is is set to sans-serif-condensed.
<string name="font_family_button_material">sans-serif-medium</string>
<string name="font_family_button_material">sans-serif-condensed</string>
This sans-serif settings are mapped to my chosen font family within the fonts setup. Typically sans-serif is fine for button text. For further customisation of the fonts I point to this question.
Button Style
Apart from using a color for the background, a xml resource file can be applied to specify the background with fancy corners, color gradients or other graphical effects, also supporting different backgrounds for different states of the button.
This part is strongly influenced by my design. I will typically use my own background.
On the other hand there is a rich system of predefined button backgrounds resource files in material design. I would like to give a short overview here, but that's beyond my skills and seems so large to be worth a topic of it's own.
The style for the background should not contain settings for width, height or margins, as this belongs into the surrounding layout. On the other hand the padding belongs into the background style.
Button styles of Material Design
In the file data/res/values/styles_material.xml I find nine button styles I may inherit from. If I write my very own, a should not forget to set a default text appearance.
The root element is Widget.Material.Button. It set's the default text appearance to ?textAppearanceButton. Hence, setting this attribute is an option to directly use the material design button styles without inheritance and yet have your customised default text appearance.
<!-- Bordered ink button -->
<style name="Widget.Material.Button">
<item name="background">#drawable/btn_default_material</item>
<item name="textAppearance">?attr/textAppearanceButton</item>
<item name="minHeight">48dip</item>
<item name="minWidth">88dip</item>
<item name="stateListAnimator">#anim/button_state_list_anim_material</item>
<item name="focusable">true</item>
<item name="clickable">true</item>
<item name="gravity">center_vertical|center_horizontal</item>
</style>
The attribute ?colorAccent is used, to set the color of Widget.AppCompat.Button.Colored. See the Android Studio Theme Editor. See #drawable/btn_colored_material.
Note that the default text appearance of Widget.AppCompat.Button.Colored varies and is not set by a customisable attribute.
<!-- Colored bordered ink button -->
<style name="Widget.Material.Button.Colored">
<item name="background">#drawable/btn_colored_material</item>
<item name="textAppearance">#style/TextAppearance.Material.Widget.Button.Colored</item>
</style>
<!-- Small bordered ink button -->
<style name="Widget.Material.Button.Small">
<item name="minHeight">48dip</item>
<item name="minWidth">48dip</item>
</style>
<!-- Borderless ink button -->
<style name="Widget.Material.Button.Borderless">
<item name="background">#drawable/btn_borderless_material</item>
<item name="stateListAnimator">#null</item>
</style>
Note that the default text appearance of Widget.Material.Button.Borderless.Colored varies and is not set by a customisable attribute.
<!-- Colored borderless ink button -->
<style name="Widget.Material.Button.Borderless.Colored">
<item name="textAppearance">#style/TextAppearance.Material.Widget.Button.Borderless.Colored</item>
</style>
Note that Widget.Material.Button.ButtonBar.AlertDialog inherits from Widget.Material.Button.Borderless.Colored. Same limitations of the default text appearance apply.
<!-- Alert dialog button bar button -->
<style name="Widget.Material.Button.ButtonBar.AlertDialog" parent="Widget.Material.Button.Borderless.Colored">
<item name="minWidth">64dp</item>
<item name="minHeight">#dimen/alert_dialog_button_bar_height</item>
</style>
<!-- Small borderless ink button -->
<style name="Widget.Material.Button.Borderless.Small">
<item name="minHeight">48dip</item>
<item name="minWidth">48dip</item>
</style>
<style name="Widget.Material.Button.Inset">
<item name="background">#drawable/button_inset</item>
</style>
<style name="Widget.Material.Button.Toggle">
<item name="background">#drawable/btn_toggle_material</item>
<item name="textOn">#string/capital_on</item>
<item name="textOff">#string/capital_off</item>
</style>
Personally I would either use one of this predefined button styles or inherit my own from Widget.Material.Button. This keeps the hierarchy of inheritance low and the code easily readable. It saves me at most three lines of code if I inherit from another style, while the code becomes less maintainable.
There are exceptions to this rule of thumb. For example #drawable/btn_borderless_material is private. So I either have to inherit from Widget.Material.Button.Colored or create a copy of the file.
Appendix
Related questions
Attributes
Defining custom attrs
Android Use custom themes to modify style attributes
Android "?colorPrimary" vs "?attr/colorPrimary"?
Inheritance issue, when using property androidTextapperance vs. property style
Colors
Setting a color based on theme
Attribute android:colorForeground not working in API 23
android themes - defining colours in custom themes
Fonts
How to set default font family for entire Android app
How to change fontFamily of TextView in Android
What is the difference between fontFamily and typeFace in android?
it's up to you and depends on your application.. also you can set a background using an xml file
eg:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="20dp" />
<solid android:color="#8c0000" />
</shape>
</item>
<item >
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="20dp" />
<solid android:color="#c62f2c" />
</shape>
</item>
</selector>
Is there a way to reference a color resource with modified alpha value in a xml resource file? What I'm looking for is something like this:
<!-- base color -->
<color name="myColor">#19AEE0</color>
<!-- redefined color with alpha - not particularly elegant -->
<color name="myColor2">#8019AEE0</color>
<!-- referenced color with alpha -->
<color name="myColorTransparent" alpha="0.5">#color/myColor</color>
I am aware that this can be easily done programmatically, but doing it the declarative way would be much clearer and more readable when defining several transparency values for the same color.
After searching around a bit to set the color accent as the ripple drawable's color, I've found that it can be done with the aid of a <selector>.
Add a color resource folder if not existing and create a new file there, whose base name will be used as color resource. For example, name it my_color_transparent.xml. Then, paste the following contents.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:color="#color/myColor"
android:alpha=".5" />
</selector>
At this point, you can reference it as #color/my_color_transparent via XML or programmatically as usual, like colors in the values folder.
NOTE:
The android:alpha attribute is applied as a mask, so the alpha is multiplied by that of the color specified via the android:color attribute. As an instance, if #color/myColor were 20% opaque and android:alpha were .5, then the opacity of #color/my_color_transparent would be 10%.
I try to change the color based on my theme. My TextView is using color-selector with different states for enabled and disabled and I want to use my theme based color in this selector.
I have followed this solution: android themes - defining colours in custom themes
My selector used as android:textColor in my view looks like this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:color="#ffffff" />
<item android:state_enabled="false" android:color="?attr/ThemeTest"/>
</selector>
with ThemeTest being my custom attribut which has a color assigned in my themes. If I use this selector as my textColor, the color is actually not what I picked but just a simple plain RED! HOWEVER if I use the custom attribut directly in my view
android:textColor="?ThemeTest"
then it works but I obviously want to do this based on the change of state of my view...
Does anybody understand this behaviour and know how to fix it? Thanks in advance!
Using a theme attribute inside a color selector XML file is only supported in the most recent versions of Android. To overcome this limitation you need to create one color selector file for each theme, and fill them with plain colors. Then create a theme attribute which points to the correct color selector depending on the theme.
source: https://plus.google.com/102404231349657584821/posts/XEeehfwanGy
edit: tested and it works flawlessly!
I want to create a style which uses the android textColorPrimary as a background color.
I tried the following which does not work, the result is my layout not beeing displayed at all.
<style name="horizontalLine">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">1dp</item>
<item name="android:background">?android:attr/textColorPrimary</item>
</style>
How do I use textColorPrimary as background color in a style?
This syntax seems to work for me, when trying to use attributes:
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="?android:textColorPrimary"
android:text="Hello"/>
(or)
<style name="MyStyle">
<item name="android:textColor">?android:textColorPrimary</item>
</style>
I can change the app theme from Holo to Holo.Light and the text color will change automatically to fit.
It doesn't work when I set it as a background of a View though - Android will crash complaining that the drawable referenced is a state list that does not specify drawables (it is a state list of colors).
Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #2: <item> tag requires a 'drawable' attribute or child tag defining a drawable
at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:178)
at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:885)
at android.graphics.drawable.Drawable.createFromXml(Drawable.java:822)
at android.content.res.Resources.loadDrawable(Resources.java:1950)
... 39 more
I am using HoloEverywhere which lets me reference the resources directly, but you should get a similar problem in the native case. I don't think the primary, non-selected, non-activated (etc.) color used as a component in the state list xml is exposed through an attribute.
In any case, the text color used is dependent on the theme that you, the app developer, chooses. If you choose to use the Holo (dark) theme then your text will be a light color, and the user won't be able to affect this. You don't need to make the your line color dynamic for your app.
To apply the ?android:attr/textColorPrimary attribute as the background of a view, you have two options.
First Option
The first option is to define a shape drawable which gets its color from the ?android:attr/textColorPrimary attribute, as follows...
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="?android:attr/textColorPrimary" />
</shape>
... and, assuming you've named this drawable rectangle_shape_with_primary_text_color.xml and placed it in your application's res/drawable folder, you can set it as the background of your style as follows...
<item name="android:background">#drawable/rectangle_shape_with_primary_text_color</item>
... or set it as the background of your view directly, as follows...
android:background="#drawable/rectangle_shape_with_primary_text_color"
Second option
The second option is to set the backgroundTint property of your style or view.
You can set the backgroundTint property of your style as follows:
<style name="horizontalLine">
<item name="android:background">#android:color/white</item>
<item name="android:backgroundTint">?android:attr/textColorPrimary</item>
</style>
Or you can set the backgroundTint property of your view directly as follows:
<View
android:id="#+id/horizontalLine"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#android:color/white"
android:backgroundTint="?android:attr/textColorPrimary" />
Note that the exact value of the background property with this approach is not important but it must be set and it cannot be set to #null or #android:color/transparent.
The error message I get for this is:
org.xmlpull.v1.XmlPullParserException: Binary XML file line #18: <item> tag requires a 'drawable' attribute or child tag defining a drawable
Doing a little digging, the specs say the background attribute should support either a colour, or reference to a drawable resource:
... Looking at the resource you're referencing, it is a StateListDrawable.
platforms/android-17/data/res/color/primary_text_dark.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="#android:color/bright_foreground_dark_disabled"/>
<item android:state_window_focused="false" android:color="#android:color/bright_foreground_dark"/>
<item android:state_pressed="true" android:color="#android:color/bright_foreground_dark_inverse"/>
<item android:state_selected="true" android:color="#android:color/bright_foreground_dark_inverse"/>
<item android:state_activated="true" android:color="#android:color/bright_foreground_dark_inverse"/>
<item android:color="#android:color/bright_foreground_dark"/> <!-- not selected -->
</selector>
However, the docs for StateListDrawable also explicitly say the drawable attribute must be defined for item elements:
https://developer.android.com/guide/topics/resources/drawable-resource.html
<item>
Defines a drawable to use during certain states, as described by its attributes. Must be a child of a <selector> element.
attributes:
android:drawable
Drawable resource. Required. Reference to a drawable resource.
... which isn't the case for the case for primary_text_dark.xml. So, it's not working because the drawable you're referencing doesn't seem to conform to the spec.
I think the workaround is to reference the colour that's used in primary_text_dark for the default state: bright_foreground_dark. Seeing as that's not public, you need to go directly to the one it references, which is:
android:background="#android:color/background_light"
I take it that you want to use native android primary text color.
<item name="android:background">#android:color/primary_text_dark</item>