TextView
in Android applications provides several attributes for styling text and various ways to apply them. You can set these attributes directly in layout, apply a style to the view or a theme to the layout, or, if you want, set textAppearance. But what of this should be used? And what happens if you combine them? textViewStyle
as the default style for your theme.TextAppearance
set that your application will use (or use / inherit from MaterialComponent styles ), and link to them directly from your viewstyle
by setting attributes that are not supported by TextAppearance
(which themselves will determine one of your TextAppearance
).TextView
attributes to the layout, but this approach can be more tedious and insecure. Imagine that you are trying to update the color of all TextViews in an application in this way. As with all other views, you can (and should!) Use styles instead to ensure consistency, reuse, and ease of updates. To this end, I recommend creating styles for text whenever you probably want to apply the same style to multiple views. It is extremely simple and largely supported by the Android view system.AttributeSet
parameter, in fact, can be viewed as a map of the XML parameters that you specify in your layout. If AttributeSet sets the style, the style is read first , and then the attributes specified directly in the view are applied to it. Thus, we come to the first priority rule.TextView
, however, has a trick, it provides the TextAppearance
attribute, which works similarly to style
. If you TextAppearance
text with TextAppearance
, then leave the style
attribute free for other styles that looks practical. Let's take a closer look at what TextAppearance
and how it works.TextAppearance
is nothing magical (for example, a secret mode for applying several styles, which you shouldn’t know about !!!!), TextView
saves you from some extra work. Let's take a look at the TextView
constructor to see what's going on. TypedArray a = theme.obtainStyledAttributes(attrs, com.android.internal.R.styleable.TextViewAppearance, defStyleAttr, defStyleRes); TypedArray appearance = null; int ap = a.getResourceId(com.android.internal.R.styleable.TextViewAppearance_textAppearance, -1); a.recycle(); if (ap != -1) { appearance = theme.obtainStyledAttributes(ap, com.android.internal.R.styleable.TextAppearance); } if (appearance != null) { readTextAppearance(context, appearance, attributes, false); appearance.recycle(); } // a little later a = theme.obtainStyledAttributes(attrs, com.android.internal.R.styleable.TextView, defStyleAttr, defStyleRes); readTextAppearance(context, a, attributes, true);
TextView
first looks to see if you’ve indicated android:textAppearance
, if so, it loads this style and applies all the properties specified there. Later he loads all the attributes from the view (which he remembers, including the style) and applies them. So we come to the second priority rule:TextAppearance
, another caution should be remembered: it supports a subset of the style attributes that TextView
offers. To better understand what I mean, let's go back to this line:obtainStyledAttributes(ap, android.R.styleable.TextAppearance);
receiveStyledAttributes
version with 4 arguments, this 2-argument version is a little different. It looks at the given style (as determined by the first id
parameter) and filters it only by style attributes that appear in the second parameter, the attrs
array. Thus, styleable android.R.styleable.TextAppearance
defines the scope of the TextAppearance
. Looking at this definition, we see that TextAppearance
supports many, but not all, of the attributes that TextView
supports . <attr name="textColor" /> <attr name="textSize" /> <attr name="textStyle" /> <attr name="typeface" /> <attr name="fontFamily" /> <attr name="textColorHighlight" /> <attr name="textColorHint" /> <attr name="textColorLink" /> <attr name="textAllCaps" format="boolean" /> <attr name="shadowColor" format="color" /> <attr name="shadowDx" format="float" /> <attr name="shadowDy" format="float" /> <attr name="shadowRadius" format="float" /> <attr name="elegantTextHeight" format="boolean" /> <attr name="letterSpacing" format="float" /> <attr name="fontFeatureSettings" format="string" />
TextAppearance
TextView
attributes that are not included in the TextAppearance
: lineHeight[Multiplier|Extra]
, lines
, breakStrategy
and hyphenationFrequency
. TextAppearance
works at the level of characters, not paragraphs, so attributes that affect the entire layout are not supported.TextAppearance
very useful, it allows us to define a style oriented to the attributes of text styling, and leaves the style
in view free for other purposes. However, it has a limited scope and is located at the bottom of the priority chain, so do not forget about restrictions.context.obtainStyledAttributes
), we actually simplified it a bit. It calls theme.obtainStyledAttributes (using the current Theme Context
'a). When checking the link , the priority order is shown, which we considered earlier, and indicates 2 more places that it searches for attribute resolution: the default style for the view and the theme.TextView
theme and take a look at a simple Button
. When you insert a <
Button
>
into your layout, it looks like this.Button
source code, you will see that it is rather meager: public class Button extends TextView { public Button(Context context) { this(context, null); } public Button(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.buttonStyle); } public Button(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public CharSequence getAccessibilityClassName() { return Button.class.getName(); } @Override public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) { if (getPointerIcon() == null && isClickable() && isEnabled()) { return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND); } return super.onResolvePointerIcon(event, pointerIndex); } }
defaultStyleAttr
in com.android.internal.R.attr.buttonStyle
. This is the default style, in effect, being an indirect conversion point, allowing you to specify the style to be used by default. It does not point directly to the style, but allows you to point to one of those listed in your topic, which it will check when attributes are resolved. And this is exactly what all the themes from which you usually inherit do, to ensure the appearance and perception of standard widgets. For example, if you look at the Material topic, it defines @style/Widget.Material.Light.Button
, and it is this style that provides all the attributes that theme.obtainStyledAttributes
will theme.obtainStyledAttributes
if you have not specified anything else.TextView
, it also suggests a default style: textViewStyle
. This can be very convenient if you want to apply some styles to each TextView in your application. Suppose you want to set the default line spacing to 1.2. You can do this with style/TextAppearance
and try to apply during code review (or maybe even with an elegant user rule in Lint), but you need to be vigilant and make sure that you recruit new team members. , be careful with refactoring, etc.TextView
in the application that defines the desired behavior. You can do this by setting your own style for textViewStyle
, which is inherited from the platform or from MaterialComponents/AppCompat
by default. <style name="Theme.MyApp" parent="@style/Theme.MaterialComponents.Light"> ... <item name="android:textViewStyle">@style/Widget.MyApp.TextView</item></style> <style name="Widget.MyApp.TextView" parent="@android:style/Widget.Material.TextView"> <item name="android:textAppearance">@style/TextAppearance.MyApp.Body</item> <item name="android:lineSpacingMultiplier">@dimen/text_line_spacing</item> </style>
AppCompatTextView
and write your own constructor with 2 arguments, be sure to pass android.R.attr.textViewStyle defaultStyleAttr
( as here ), otherwise you will lose the behavior of the parent class.theme.obtainStyledAttributes
will look directly into the theme itself. That is, if you add a style attribute to your theme, for example, android:textColor
, the view system will select it as a last resort. As a rule, it is a bad idea to mix theme attributes and style attributes, that is, what you apply directly to the view should, as a rule, never be set for the theme (and vice versa), but there are a couple of rare exceptions.android:buttonStyle
that your android:textViewStyle
does not catch. Instead, you can specify the font in your theme: <style name="Theme.MyApp" parent="@style/Theme.MaterialComponents.Light"> ... <item name="android:fontFamily">@font/space_mono</item> </style>
Toolbar
pick up this font, since it contains a title that is a TextView
. The Toolbar class itself, however, defines a default style that contains a titleTextAppearance
, which defines android:fontFamily
, and directly sets it in the TextView
header, overriding the theme level value. Topic-level styles can be useful, but they are easy to override, so make sure they apply properly.TextView
while filling. Any style applied after filling (for example, textView.setTextColor(…)
) will override the declarative styling. TextView
also supports smaller styles via Span
. I will not go into this topic, since it is described in detail in the articles by Florina Muntenescu .Source: https://habr.com/ru/post/456110/
All Articles