I've seen it used in various XML files but I can't find any actual definition of what that ?android: does. I'm assuming it just means inherit it from the parent theme if the attribute exists in the parent theme.
It is used to reference a style attribute in a theme. See Accessing resources - referencing style attributes
Related
What's the parent of Theme.AppCompat.Light.NoActionBar? I can't find a "parent" attribute in Android SDK resources. I guess it should be Theme.AppCompat.Light. But I didn't find any document to prove that.
You can inherit styles by using dot instead of using parent (docs). So Theme.AppCompat.Light is parent of Theme.AppCompat.Light.NoActionBar
You can also inherit styles (except those from the platform) by extending a style's name with a dot notation, instead of using the parent attribute. That is, prefix the name of your style with the name of the style you want to inherit, separated by a period.
I am working on an example about Support Library and Toolbar, this is the code of the layout on the Android documentation
<android.support.v7.widget.Toolbar
android:id="#+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
It is the first time I see these ?attr and I have no clue about what they mean or where are these values stored. Are these custom or are they predefined on the Android framework?
Reference: Android Toolbar Documentation
?attr/ references to attributes. Attributes are values specified in an app's theme. The attributes in your example are all values specified in the themes provided by the support library. Android also has its very own attributes which can be used with ?android:attr/.
The actual value that is going to be used in the end depends on the theme used to inflate the said layout. This theme can be specified in the manifest in the <application/> block for an app wide theme or in the <activity/> block for a specific activity. You can also override this theme during runtime by using a different context (see ContextThemeWrapper and LayoutInflater)
It is considered good practice to use theme attributes instead of hardcoded values in your layouts, as it allows for easy customization. For example, when you create custom views, you can use ?attr/colorAccent so that the user of the view doesn't have to provide a color, and it is going to use the colorAccent used in the app themes instead.
This becomes even more relevant today, as with the introduction of Dark Themes in Android Q, your layouts should specify an attribute so that the end value is different when using a light theme vs a dark theme.
A style attribute resource allows you to reference the value of an
attribute in the currently-applied theme.
https://developer.android.com/guide/topics/resources/accessing-resources.html#ReferencesToThemeAttributes
Rather than setting a static color (#ffffff or a #color resource)
we can delegate to the theme by using the ?attr/themeAttributeName
syntax. This syntax means: query the theme for the value of this
semantic attribute.
This post on Medium gives a fairly detailed explanation on styles and themes.
Is there anyway to change theme attributes dynamically? For example,set the "android:colorPrimary" attribute for a Theme. I know I can apply different Themes to Activity when it creates, but it requires predefined styles in resources, which means the attributes are fixed. If I want to download one Theme from server(it can be a config file with some color attribute defined), this can't work out.
Theme.NoTitleBar is defined as below.
<style name="Theme.NoTitleBar"> // It does not have parent="Theme"
<item name="android:windowNoTitle">true</item>
</style>
But, it inherits all attributes of Theme.
I don't know how it works.
It inherits all attributes of Theme because it's basically an extension of that theme. It's somewhat similar to saying Class A extends B, although there are no distinctions in the visibility of attributes or anything.
Note how Theme.NoTitleBar is prefixed with Theme, that's where all the attributes come from.
Generally, the name of a style provides a hierarchical approach to structuring and naming styles and substyles. You can use the hierarchical characteristic as an alternative to the parent attribute for styles you've defined yourself. For extending existing platform-defined styles, you always need to use parent.
All this is explained pretty well in the Styles and Themes documentation, subsection Inheritance. Two relevant quotes that summarize most of above:
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.
Note: This technique for inheritance by chaining together names only
works for styles defined by your own resources. You can't inherit
Android built-in styles this way. To reference a built-in style, such
as TextAppearance, you must use the parent attribute.
Head over to the link for more details or to see some examples.
When using android styles, one can specify a parent style like:
<style name="MyStyle" parent="#style/ParentStyle"></style>
Is is possible to specify multiple parents? If so, how?
According to documentation, the syntax for parent attribute value is #[package:]style/style_to_inherit (where package: is optional) so a reference to just a single style resource is allowed.