As my title, when I'm using a theme, style or text appearance, which one takes precedent?
Is there any way I can use all three of them? Thanks!
According to the docs, the priorities are as follows:
Applying character- or paragraph-level styling via text spans to
TextView-derived classes
Applying attributes programmatically
Applying individual attributes directly to a View
Applying a style to a View
Default styling
Applying a theme to a collection of Views, an activity, or your
entire app
Applying certain View-specific styling, such as setting a
TextAppearance on a TextView
Related
I read about Android styles and themes today and tried to apply it to a list in my app as a test. The app has a list element which have TextViews added to it programmatically.
According to the docs applying a style as a theme affects child views too.
So I tried this:
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/TextAppearance.AppCompat.Small"/>
I expected that the TextView texts in the list became small, but nothing happened.
I also tried #style/TextAppearance.MaterialComponents.Headline1, but it had no effect either.
Why is that?
I didn't change any of the style or theme settings myself. I use the default settings which Android Studio generated for the project.
Shouldn't applying a style as a theme to a view like above change something?
You are using the style "TextAppearance.AppCompat.Small" which is applicable to a TextView and not a generic one like ListView.
You need to apply the style to the list item which is the TextView. You can create a custom style for text appearance, font, sizing, etc and reuse it in your entire app.
If you are creating your views programmatically, you can use a custom adapter (which extends your default adapter), override getView method to apply your style. Refer this
Refer to this awesome article by #Nick Butcher
Hi I have a view with a form, and all button, labels, EditText, etc, are defined in a styles files, for example, for EditText I have app_edit_text and app_edit_text_error, my question is how can change in EditText the style from app_edit_text to app_edit_text_error?.
Thanks!
To be honest you can't change style programaticaly. You can only change text
appearance using setTextAppearance(int resId) method:
https://developer.android.com/reference/android/widget/TextView#setTextAppearance(int)
For your purpose you can use setError(String error) method of EditText or implement self states and handle it in EditText subclass. Here is good post about custom states: How to add a custom button state
You can't change styles programatically. You can either replace them with a new Instance (you can specify the styles in the constructor only) or you can use it with a new theme since theme can be changed programatically.
Themes
I was trying to apply a style to an EditText to change it's colorAccent, I tried to set its style and android:textAppearance, but it completely ignored my new settings. The only way I got it to work was by setting its android:theme.
Am I doing something wrong or is this expected behavior? Why?
My style:
<style name="bright_color_cursor" parent="AppTheme">
<item name="colorAccent">#color/primaryBrightColor</item>
<item name="android:textColorHighlight">#color/primaryBrightColor</item>
</style>
My EditText:
<EditText
android:id="#+id/edit_text"
android:theme="#style/bright_color_cursor"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="#android:color/transparent"
android:ems="10"
android:hint="#string/hello"
android:inputType="textCapWords"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#+id/name_edit_text"
app:layout_constraintTop_toBottomOf="#+id/divider" />
Changing android:theme to any of this settings won't work:
style="#style/bright_color_cursor"
or
android:textAppearance="#style/bright_color_cursor"
Yep, this behavior is to be expected with an EditText. We need to style it by using the android:theme property.
When using #style, the EditText doesn't use the values that we set (and thus the style seems to be ignored). This is, because the EditText creates some children views that are not being styled. See my detailed explanation below.
Detailed explanation and the cause
1) First, the meanings of the options tried and what these do:
style: (Note: not prefixed with android:): This sets the styles only for the component itself and does not change the styles of it's underlying children views/layouts.
android:theme: This basically applies to style to itself and applies the style to it's children views/layouts.
android:textAppearance: This one behaves just like #style for styling.
2) The EditText functionality
As we can imagine: an EditText is not just a simple view. It has a background drawable and handles interaction and such. It simply needs some additional views (and logic) for this functionality to work.
For the functionality of the EditText, it adds some subviews as children to be able to do what we expect from it.
3) Back to theming
The subviews that the EditText adds to do it's functionality, are styled just like the other views are being styled. Which means that the child views only inherit the style when we use the android:theme property. Because this property causes it to style the children views too.
And, if we use #style on the edittext, the children will not get this style.
4) Why this happens (only) for EditText?
Well, not really only... The base view of an EditText is a TextView, but a TextView doesn't provide the functionality that an EditText needs. So the EditText adds additional functionality itself.
A Button for example has the TextView as base too. But this class has enough views with the text and background it gets from the base class, and thus a Button doesn't need to add additional views for it's functionality. So for this, using #style works as it creates no children views to style.
Having said this, a small remark:
In fact, in the source the TextView actually contains the editting logic, but in case of a Button it simply doesn't execute that part of code. (A button doesn't need the Editting functionality, thus it's not being executed)
I want a specific TextView to have the same font size as a Button, but they appear to be different. If my Button is not setting a custom textSize, how can I grab this value from the current theme and set it to the textSize of my TextView?
It should be fairly simple with styles. Buttons parent is android.widget.TextView so you could make a style that uses this as parent and overwrite the default textSize. Then let both use this style.
I have an android application that I'm working on with a custom theme applied to it in the android manifest on the main activity itself. This activity creates a listview, which has the style applied to it.
If I create a custom layout for that listview, including a separate xml file for the rows themselves, and I apply styling directly to those layouts, does this style overwrite the overall style for the application? I'm trying to get a grasp on the hierarchy of events as far as how styling and themeing works.
The way I'm GUESSING it works in my example is: apply style for row, referenced by row layout xml > apply style for overall listview, referenced by listview layout xml > apply style from custom theme, referenced by style xml referenced by android manifest
Am I right? Or am I approaching this incorrectly. (just for confusions sake, by ">" I mean has a greater importance than)
If you've specified the same attributes in multiple places, the list below determines which attributes are ultimately applied. The list is ordered from highest precedence to lowest:
Applying character- or paragraph-level styling via text spans to TextView-derived classes
Applying attributes programmatically
Applying individual attributes directly to a View
Applying a style to a View
Default styling
Applying a theme to a collection of Views, an activity, or your entire app
Applying certain View-specific styling, such as setting a TextAppearance on a TextView
Hope I am understand your question right here...
The styles you define in styles.xml will always overwrite the styles coming from the theme currently used by android.
But this only works for the attributes you overwrite.
If you leave an attribute untouched, android will provide the style for it, and sometimes this comes bite you in the butt :)
This system is best described like this:
A textview requires an attribute example
<item name="android:textColor">#00FF00</item>
Android will first look in the original layout.
If not found, it will look into your custom styles.
If not found, it will look into android styles.
Hope this helps.
The standard themes have lines like which define the ListView style:
<item name="listViewStyle">#android:style/Widget.ListView</item>
In your own theme you can do a
<item name="listViewStyle">#style/MyOwnListView</item>
Something that is not defined in the ListView style (own or default) will be what is defined in the theme if you have defined it there.