

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" /> TextAppearanceTextView 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