In appcompat-v7:22.2.0, two resource hierarchies declared in values.xml are confusing to me.
For example, below styles are found in same file: values.xml in appcompat-v7:22.2.0
<!-- From: file:/usr/local/google/buildbot/repo_clients/https___googleplex-android.googlesource.com_a_platform_manifest.git/lmp-mr1-supportlib-release/frameworks/support/v7/appcompat/res/values/styles.xml -->
<style name="TextAppearance.AppCompat.Widget.ActionBar.Title"
parent="Base.TextAppearance.AppCompat.Widget.ActionBar.Title"/>
<style name="TextAppearance.Widget.AppCompat.Toolbar.Title"
parent="Base.TextAppearance.Widget.AppCompat.Toolbar.Title"/>
There is effectively no difference.
From line 323 of styles_base.xml:
<style name="Base.TextAppearance.Widget.AppCompat.Toolbar.Title"
parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
</style>
The Toolbar.Title base style is just an alias to the ActionBar.Title style. I am assuming that Google organized it like this because they are attempting to replace the word "Action Bar" with the word "Toolbar" in our vocabulary, but wanted to make these styles easy to find.
What's the difference between the resource hierarchy of the two: Appcompat.Widget and Widget.AppCompat?
Someone just decided to name them differently. Since both styles have an explicit parent, neither one will inherit any attributes by default anyway. My guess is that it is simply a mistake.
Related
I know that
we have not to use parent attribute. We prefix one style to another
style separating by a period(.)
so in this style, does it have a circular inheritance?
<style name="TextAppearance.A" parent="TextAppearance.A.B">
<item name="android:textAlignment">viewStart</item>
<item name="android:gravity">start</item>
</style>
TextAppearance.A.B inherits from TextAppearance.A because of android dots' syntax.
but TextAppearance.A inherits from TextAppearance.A.B because of android paretn syntax.
Is it really a problem?
Technically As per Android Documentation I dont think this is possible,
Because this will lead to duplication of style, If you refer to same as Diamond Problem it will be one of those, also android prevents you from inheriting from more than one style.
Further Imagine if you have one attribute which is defined in style A also in Style B, it will be a problem at compile time that which attribute to choose from both.
For More Details please refer to android documentation
https://developer.android.com/guide/topics/ui/look-and-feel/themes
UPDATE: As pointed out in the comments, 'Widget.AppCompat.EditText' is the correct parent style for an AppCompatEditText subclass. In my case, the real issue was I had forgotten to assign a value to our control's default style attribute in our theme, so our control wasn't getting any style to use as a default.
However, this question still could use an answer as to how one properly identifies which style to use as a parent when defining your own default styles when subclassing the standard controls. As such, I've also renamed its title.
As such, I'm leaving this open in hopes someone can answer that question since it will help any who wish to do something similar.
We're trying to define a common look-and-feel for all AppCompatEditText controls used throughout the app. As such, rather than having to manually apply the 'style' attribute on each usage, we're instead trying to replace the default style with our own.
Replacing the default style is actually the easy part. What isn't is knowing what the parent style for our style should be set to so we still have all aspects of the original style which we haven't explicitly overwritten with those in ours.
Digging in the source code for AppCompatEditText, it shows the default style to be stored in R.attr.editTextStyle but I'm not sure where now to look to see what value is stored in it.
Experimenting too didn't get us anywhere. No matter what we have tried so far, we lose the default appearance completely. No underline, no background, no padding, nothing. Just the values we've set, which means it's not picking up the parent style.
We've tried the following without success...
<style name="ZinEditText" parent="android:Widget.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">#dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">#dimen/defaultLineSpacing</item>
</style>
<style name="ZinEditText" parent="Widget.AppCompat.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">#dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">#dimen/defaultLineSpacing</item>
</style>
<style name="ZinEditText" parent="Base.V7.Widget.AppCompat.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">#dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">#dimen/defaultLineSpacing</item>
</style>
<style name="ZinEditText" parent="Widget.Holo.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">#dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">#dimen/defaultLineSpacing</item>
</style>
As I said, none of the above seemed to work.
So how does one find the actual parent style to use?
To address the immediate issue, the default style for an AppCompatEditText is Widget.AppCompat.EditText. The second example you've shown is the correct one:
<style name="ZinEditText" parent="Widget.AppCompat.EditText">
...
This needs to be set as the editTextStyle in your app theme.
<style name="AppTheme" parent="#style/Theme.AppCompat">
<item name="editTextStyle">#style/ZinEditText</item>
...
Finding these default styles and attributes is not well documented anywhere officially, as far as I'm aware. The official documentation for Styles and Themes simply directs one to the various R.attr pages for the framework and support packages, to "discover" what's available. However, a generally reliable way to find this for most Views that allow a default style is to inspect the source code.
A View subclass will often implement at least three constructors: one that takes only a Context; one that takes a Context and an AttributeSet; and one that takes a Context, an AttributeSet, and an int for defStyleAttr, a default style attribute. This attribute is what we're looking for. It will usually have a sensible name, like editTextStyle, textViewStyle, checkboxStyle, etc. If you already know the name, you can skip checking the View class for it.
In Views that chain their constructors, this attribute will be normally be in the call to the three-parameter constructor from the two-parameter one. In AppCompatEditText, we can see that the name of this attribute is editTextStyle.
public AppCompatEditText(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.editTextStyle);
}
After we've got the name for the attribute, we then head to the res/values/ directory for the platform or support package the View is in. The default value will be in the relevant themes*.xml file for your app's parent theme.
For the platform themes, there is a base themes.xml, and a few others for specific theme versions, such as Holo and Material.
For support library Views, these theme files will be under the package-specific res/values/ directory, and the default attribute value may be in themes.xml or themes_base.xml.
In v7 appcompat, our app's exact parent theme is likely in v7/appcompat/res/values/themes.xml, though most of the themes there are just direct aliases for base themes; i.e., they don't override any of their parents' attribute values. The default for AppCompatEditText is actually in v7/appcompat/res/values/themes_base.xml. There are separate entries for different themes - the regular, and the light - but they are both the same.
<item name="editTextStyle">#style/Widget.AppCompat.EditText</item>
This is enough to determine which style to use as our parent, but should we want to check out the style specifics, we can then refer to v7/appcompat/res/values/styles.xml, where we find that style's parent:
<style name="Widget.AppCompat.EditText" parent="Base.Widget.AppCompat.EditText"/>
which leads us to v7/appcompat/res/values/styles_base.xml:
<style name="Base.Widget.AppCompat.EditText" parent="Base.V7.Widget.AppCompat.EditText" />
<style name="Base.V7.Widget.AppCompat.EditText" parent="android:Widget.EditText">
<item name="android:background">?attr/editTextBackground</item>
<item name="android:textColor">?attr/editTextColor</item>
<item name="android:textAppearance">?android:attr/textAppearanceMediumInverse</item>
</style>
I am in bit confusion to adding parent style to new style. But both are working. But i want to know which is correct way first one or second one? or is there any other way ?
<style name="customView" parent="viewline">
<item>....
and
<style name="customView" parent="#style/viewline">
<item>....
Thanks
Both are correct as you said. At here there is no any drawback to use any of them.
<style name="customView" parent="viewline">
denotes that the parent style is in same file. And
<style name="customView" parent="#style/viewline">
denotes that parent style is somewhere (may be i another file) in style directory. Thats it.
May I know what is the difference between styles.xml and themes.xml? To me, they just look same as both XML are in the same format.
<style name="...
<item name="...
So, in my app which provide customization coloring, size, drawable, ... do I need both styles.xml and themes.xml as well? How should I decide which XML to put in which file?
Out of the whole page of the Styles and Themes. You may be looking for this line.
When you apply a style to a single View in the layout, the properties
defined by the style are applied only to that View. If a style is
applied to a ViewGroup, the child View elements will not inherit the
style properties—only the element to which you directly apply the
style will apply its properties. However, you can apply a style so
that it applies to all View elements—by applying the style as a theme.
When you apply as theme, it changes everything in scope, depending if you applied it on Activity or Application. Style is more 'local'.
Quoted from Android API guide:
To create a set of styles, save an XML file in the res/values/ directory of your project. The name of the XML file is arbitrary, but it must use the .xml extension and be saved in the res/values/ folder.
The root node of the XML file must be <resources>.
Full documentation
So I guess it really doesn't matter if you put any styles in any files as long as it's an xml file which locates in res/values/ folder.
There is no functional difference between styles.xml and themes.xml as many answers have indicated.
It is worth noting that Google's iosched2014 app has ONLY a styles.xml (no themes.xml).
https://github.com/google/iosched
Taken from the Styles and Themes document, in the Defining Styles section:
To create a set of styles, save an XML file in the res/values/ directory of your project. The name of the XML file is arbitrary, but it must use the .xml extension and be saved in the res/values/ folder.
The root node of the XML file must be <resources>.
I am just realizing that for example Toolbar text colors go into a theme declaration, and for other aspects go into a style declaration
<style name="ToolbarTheme" parent="ThemeOverlay.AppCompat.Light">
<item name="android:textColorPrimary">#android:color/white</item>
<item name="android:textColorSecondary">#android:color/white</item>
</style>
<style name="ToolbarStyle" parent="Base.Widget.AppCompat.Toolbar">
<item name="android:minHeight">?attr/actionBarSize</item>
<item name="android:background">#color/colorPrimary</item>
</style>
And in the toolbar declaration
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/ToolbarStyle"
android:theme="#style/ToolbarTheme">
</android.support.v7.widget.Toolbar>
I tried to omit the theme by moving its items into the style, but that didn't work. So in this case it seems as these are just styles which are as theme since they affect the inherited children in the toolbar such as the textfields.
Hi here is an article regarding to the difference between styles and themes XML in android please go through
And also here the android documentation regarding to styles and themes in Android.
I tried changing the appearance of a spinner and I partly succeeded. I'm doing this via overriding parts of the theme. I managed to change the text size of the spinner item (i.e. the text size in the drop down button) with my themes.xml and styles.xml:
My themes.xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomTheme" parent="#android:Theme.Holo.Light">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:spinnerItemStyle">#style/CustomSpinnerItem</item>
</style>
</resources>
My styles.xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomSpinnerItem" parent="#android:Widget.TextView.SpinnerItem">
<item name="android:textAppearance">#style/CustomTextAppearance</item>
</style>
<style name="CustomTextAppearance">
<item name="android:textSize">30dp</item>
</style>
</resources>
However I cannot find the attributes that are responsible for the text appearance of the items in the dropdown list of the spinner. I tried dropDownItemStyle amongst other things. In my opinion the attribute names are not self-explanatory, so I wanted to know whether there is a documentation of what attribute does what in a style to find out which attributes to override. I found it very cumbersome to trace back all the styles used in a theme via the themes.xml and styles.xml of the platfrom and then try to find the right attributes via trial and error.
I know that one can change the appearance by passing layouts to the adapter, however, this is not really what I was looking for, since (as far as I know), you can only use inheritance in styles and not in layout xml files. If I created a custom layout for the adapter I'd have to create 9-patch images etc., which I think is a bit too time consuming in case I only want to change the text size.
Of course it's possible that I misunderstood the whole concept, since I'm new to Android ;)
You probably have found out the answer since you asked but for others looking at similar questions:
I do not know of a list of attribute names with good explanation of what they do (R.attr's page mostly gives information that is already in the name) but the way I do it is:
Start from the element I give to setDropDownViewResource(), in my case: android.R.layout.simple_spinner_dropdown_item and find.
Find its layout definition in \sdk\platforms\android-17 (specific platform version to avoid redundant results).
Get its style from the layout file. In this case: ?android:attr/spinnerDropDownItemStyle
We now have the attribute name we need.
It's better to do it that way rather than try to guess what attribute to use because you know which attribute the system itself use so it's very likely to be the correct one (unless there's a bug).
If I created a custom layout for the adapter I'd have to create
9-patch images etc.
Well, no, the layout determines what kind of GUI element you would have (a textfield, a spinner, an imagebutton, a custom element...), not how they are styled (nine-patch backgrounds, text colors...), so you still would have to mess with styles to get the right appearance.
For example, for visual consistency I ported the button, checkbox and spinner style from Theme.Holo to Gingerbread, yet I did not mess with layout, all I did was the aforementioned steps plus looking up the result (spinnerDropDownItemStyle in the above example) in themes.xml, which gave me the style name (e.g.: Widget.Holo.DropDownItem.Spinner).
Then I looked that up in styles.xml and imported it (and any parent*) in my project's styles.xml, searching and copying any Holo specific reference in my project and adjusting the namespace accordingly (add android: to attributes and replace ?android:attr with #style for what I copy to my styles.xml file).
So far I haven't had to mess with layouts at all (even the presence of radio buttons in spinner dialogs on Gingerbread is determined by an xml attribute: android:checkMark).
If a style has no parent attribute (like Widget.Holo.DropDownItem.Spinner) then its parent is the same style minus the last element (e.g.: Widget.Holo.DropDownItem)