In-depth understanding of Android custom attr Style styleable and its application

Source: Internet
Author: User

Believe that every Android ape in development has encountered the need to customize their own View needs, if you want to xml specify some of our own parameters, we need to declare one styleable , and in the inside to define some of the attr properties, the process is believed to be more understanding. Of course, attributes do not necessarily need to be View used in conjunction with one another, for example, I would like to use a Theme simple configuration of a library in a style few parameters, what should be done? Today, I was in the encapsulation of a library in this place wasted more time, and finally no way to search the data everywhere, recorded here, I believe it is helpful to everyone.

The relationship between attr and styleable

First of all, be clear, attr do not rely on styleable , styleable just for attr the convenience of use .
We can define our own properties completely styleable , such as defining some properties directly in the resources file:

<attr name="custom_attr1" format="string" /><attr name="custom_attr2" format="string" />

Defining one attr will generate an ID in the R file, so when we go to get this property, we must call the following code:

int[] custom_attrs = {R.attr.custom_attr1,R.custom_attr2};TypedArray typedArray = context.obtainStyledAttributes(set,custom_attrs);

And by defining a styleable , we can automatically generate a int[in the R File], and the int inside the array is defined in styleable attr 's ID. So when we get the property, we can use the styleable array directly to get a series of properties.

  <declare-styleable name="custom_attrs">             <attr name="custom_attr1" format="string" /> <attr name="custom_attr2" format="string" /> </declare-styleable>

Get:

  TypedArray typedArray = context.obtainStyledAttributes(set,R.styleable.custom_attrs);

As can be known from the above example, define one declare-styleable , and automatically provide an array of attributes for us when we get the property. In addition, I think declare-styleable the use of the way to help us we put the relevant attributes together, there is a concept of grouping, the use of properties more explicit scope.

Obtainstyledattributes function Get Property

In fact, we have used the previous obtainStyledAttributes to get the property, now look at the declaration of this function:

    • Obtainattributes (AttributeSet set, int[] attrs)//Get properties in Attrs from the property set in layout
    • Obtainstyledattributes (int[] attrs)//Get properties from Attrs in the system theme
    • obtainstyledattributes (int resid,int[] attrs)//Read properties from the style defined by the resource file
    • Obtainstyledattributes (AttributeSet set, int[] attrs, int defstyleattr, int defstyleres)
      This is the most complicated kind of situation, which is followed by detail.

Is it that many overloaded methods have been seen? In fact, you only need to understand the parameters of the method can be used to control the use of various methods. The so-called get property, just need two parameters: first, I need to get those attributes; second: Where do I get these attributes (data source).

Attrs

attrs: int[], the arguments in each method are the ones that tell the system to get the values of those properties.

Set

set: Represents a layout collection of attributes that are added directly from a file View , such as: android:layout_width="match_parent"。注意,这里面的属性必然是通过 XML 配置添加的,也就是由 layoutinflater 加载进来的布局或者 View ' has this property set.

Now you know why we should at least rewrite the (context, AttributeSet set) constructor When we define the view? Because when not rewritten, we will not be able to get the properties configured in the layout!! Of course, because of this, Layoutinflater will invoke the view's (context context, AttributeSet Attrs) constructor by reflection when inflater the layout.
There are actually two kinds of data sources in set, and of course it will be included in the set. One is the direct use of android:layout_width="wrap_content" this direct designation, and one is style="@style/somestyle" specified by this.

Defstyleattr

This parameter is the key to this article, but also the key to customizing a style that can be Theme configured in, first look at a chestnut bar:
If I wanted to modify all of the styles by setting a style in the system theme, textview you would typically do this:

<StyleName="Apptheme"Parent="Theme.AppCompat.Light.DarkActionBar" >//set textview in theme style < item name= " Android:textviewstyle "> @style/textviewstyle</item> </style>< style name= "Textviewstyle" parent= "Android:style/widget.textview" >< Span class= "Hljs-rule" > <!--specify some properties-- </STYLE>         

The first android:textViewStyle is actually an ordinary attribute defined in the resource file attr , it's format="reference" . The question TextView is, how do we know what we have defined textviewstyle ? This is actually defStyleAttr the scenario: Define theme Configurable styles.

  Publictextview (context Context, AttributeSet attrs) {//The specified property textviewstyle to Defstyleattr, then the system will go to search theme for the style you configured for this //property this (context, attrs, Com.android. Internal. R.attr.textviewstyle); } public TextView (context Context, AttributeSet attrs, int defstyleattr) {this (context, Attrs, defstyleattr, 0); //finally called to the fourth constructor of view, called obtainstyledattributes TypedArray a = Theme.obtainstyledattributes (attrs, Com.android. Internal. R.styleable.textviewappearance, Defstyleattr, defstyleres); }
Resid=defstyleres

resId or defStyleRes: Read directly from a style defined in the resource file.

Null

Take a look at the second method, attrs where does the data come from, except that there is no attribute value source specified in the attribute set? It turns out that we can specify the value of the property directly in the theme, then the NULL property is read directly from Theme .

Did you get a little confused about seeing this place? It doesn't matter, patience to see, there is an example, after reading the example you look back to see here the explanation is OK.

Obtainstyledattributes of four parameters

Looking at this method, the returned result is also the set of properties contained in Attrs (int[]) that we care about. What about the data source? A total of 4,,,, set defStyleAttr NULL defStyleRes If an attribute is defined in more than one place, then whichever is it?

The priority levels are as follows:
set> defStyleAttr (Theme configurable style) > defStyleRes (Default Style) > NULL (directly specified in the topic)

The chestnuts are finally here!! -github

attrThe resource file is defined as follows:

Defining properties<Declare-styleableName="Custom_attrs" ><attrName="Custom_color1"format="Color" ></Attr><attrName="Custom_color2"format="Color" ></Attr><attrName="Custom_color3"format="Color" ></Attr><attrName="Custom_color4"format="Color" ></Attr><attrName="Custom_color5"format="Color" ></Attr></declare-styleable>//defining theme Configurable style<attrName="Custom_style"format="Reference" ></Attr>//define default style<StyleName= "Default_style" > <item name= "custom_color1" > #ff333333 </< Span class= "Hljs-tag" >item> <item name= " custom_color2 "> #ff333333 </item> <item name= "custom_color3" > #ff333333 </item> <item name= "custom_color4" > #ff333333 </< Span class= "Hljs-tag" >item></STYLE>    

stylesThe resource file is defined as follows:

<style name="Apptheme"Parent="Theme.AppCompat.Light.DarkActionBar" >Configure Style <item Name="Custom_style" > @style/custom_theme</item>Specify <item name= directly in the topic"Custom_color1" >#ff444444 </item> <item name="Custom_color2" >#ff444444 </item> <item name="Custom_color3" >#ff444444 </item> <item name="Custom_color4" >#ff444444 </item> <item name="Custom_color5" > style <style name="Custom_theme" > <item name= #ff444444 </item> </style>/Themes "Custom_color1" >#ff222222 </item> <item name="Custom_color2" >#ff222222 </item> <item name="Custom_color3" >#ff222222 </item> </style> //style referenced directly in the layout file, The end will be put in set <style name="MyStyle" > <item name="Custom_color1" >#ff111111 </item> < Item name="Custom_color2" >#ff111111 </item> </style>      

The layout is defined as follows:

  <com.exmp.MyCustomView    android:layout_width="wrap_content" android:layout_height="wrap_content" android:style="@style/myStyle" app:custom_color1="#ff000000" > </com.exmp.MyCustomView>

In the constructor of the Mycustomview:

PublicMycustomview (context Context) {this (Context,null);} public MyCustomView (context Context, AttributeSet set) {this ( Context, set, R.attr.custom_style);} public LinearRecyclerView (context Context, AttributeSet set, int Defstyle) {Super (context, set, Defstyle); final TypedArray a = Context.obtainstyledattributes (set, R.styleable.custom_attrs, DefStyle, R.style.default_style)}              

Once configured, the TypedArray values obtained in the properties are:
custom_color1= #ff000000//directly specified in the layout file with highest priority
custom_color2= #ff111111//layout as specified by style, also included in set, priority second
custom_color3= #ff222222//layout style by configuring styles in themes
custom_color4= #ff444444//specified directly by the system theme
custom_color5= #ff444444

Here we see that our default style has no effect because the default style is not effective until defstyle (configurable style in theme) is not 0 and Defstyle is already configured in theme.

TypedArray

We see that after we get the value of the property, we return a Typedarray object, what's the ghost? Typedarray mainly has two functions, the first is to transform the attr relationship between ID and attribute value array, and the second is to provide some types of automatic conversions, such as getString when we, if you are @string/hello set up in this way, TypedArray will automatically go to the ResId corresponding stringread from the resource file. In the final analysis, it's all for the convenience of getting property parameters.

Example-github

Back to the beginning

Now we should know how to add to our customizations View in the topic configurable Style , mainly through
obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)method to do, note that, defStyleAttr and defStyleRes both can be set to 0 to indicate not to search for configurable styles and default styles.

The question comes, if to implement my second requirement for a common class to add a style that can be configured in theme (not primarily for business parties to use the library when configured or to pass in some simple values, this is not the pros and cons of this approach, only to discuss the feasibility)? It's actually very simple:

First define:

  <attr name="config_style" reformat="referenc" />  public class ClassNeedConfig { public ClassNeedConfig(Context context) { //因为这个类不是通过Inflate进来的,所以肯定没有set,直接给null就ok //attrs 你需要获取的属性,通常是自己定义的 //指定在Theme中搜索的属性 // 0表示不去搜索默认的样式 TypedArray a = context.obtainStyledAttributes(null,attrs,R.attr.config_style,0); }}

This article mainly refer to:
Android's in-depth understanding of custom properties in Android
The meaning of Defstyle in the third parameter of the custom style in Android and the view's constructor

2016-01-14 Update
The priority is as follows: Set>defstyleattr (theme configurable style) >defstyleres (default style) >null (directly specified in the topic)
This priority needs to be explained that the Defstyleres only takes effect if the defstyleattr is 0 or not configured in the topic, so the above example
custom_color4= #ff444444 instead of 333333, because at this time the defstyleattr we configured.



Wen/Zhu Yunzhinan (Jane book author)
Original link: http://www.jianshu.com/p/61b79e7f88fc
Copyright belongs to the author, please contact the author to obtain authorization, and Mark "book author".

In-depth understanding of Android custom attr Style styleable and its application

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.