1. Introduction
For custom attributes, you are certainly not unfamiliar, follow the following steps, you can achieve:
- Customizing a CustomView (extends View) class
- Write Values/attrs.xml, where you write label elements such as styleable and item
- CustomView using custom attributes in a layout file (note namespace)
- obtained by Typedarray in the construction method of the CustomView
PS: If you are unfamiliar with the above steps, it is recommended to familiarize yourself with it before continuing ~
So, I have a few questions:
- How did the above steps work?
- What is the meaning of styleable? Can you not write? I custom attribute, I declare the attribute is good, why must write a styleable?
- If the system already has a semantically more explicit attribute, can I use it directly?
- One of the parameters in the construction method is called
AttributeSet
(Eg:mytextview (context context, AttributeSet attrs)) This parameter looks at the name of the array that contains the arguments, so can I get my custom properties through it?
- What the hell is Typedarray? From where do you want me to use it?
Well, in view of these issues, we can consider how to answer? Or said: Lao Tzu will recite the above 4 steps is enough ~ ~
2. Common examples
The following example answers the above questions, the question order is uncertain ~ ~ We first look at a common example, namely the code of the above steps.
- Declaration file for custom properties
<?XML version= "1.0" encoding= "Utf-8"?><Resources> <declare-styleablename= "Test"> <attrname= "text"format= "string" /> <attrname= "Testattr"format= "integer" /> </declare-styleable></Resources>
Packagecom.example.test;ImportAndroid.content.Context;ImportAndroid.content.res.TypedArray;ImportAndroid.util.AttributeSet;ImportAndroid.util.Log;ImportAndroid.view.View; Public classMytextviewextendsView {Private Static FinalStringtag=mytextview.class. Getsimplename (); PublicMytextview (Context context, AttributeSet attrs) {Super(context, attrs); TypedArray Ta=context.obtainstyledattributes (Attrs, r.styleable.test); String text=ta.getstring (r.styleable.test_testattr); intTextattr = Ta.getinteger (R.styleable.test_text, 1); LOG.E (TAG,"Text =" + text + ", textattr =" +textattr); Ta.recycle (); }}
<Relativelayoutxmlns:android= "Http://schemas.android.com/apk/res/android"Xmlns:tools= "Http://schemas.android.com/tools"Xmlns:zhy= "Http://schemas.android.com/apk/res/com.example.test"Android:layout_width= "Match_parent"Android:layout_height= "Match_parent" > <com. Example.test.MyTextView android:layout_width= "100DP"Android:layout_height= "200DP"zhy:testattr= "520"Zhy:text= "HelloWorld" /></Relativelayout>
OK, everybody spend 3s sweep, run the result is:
520
It should be no surprise, note that my styleable name is written in test, so this does not require that the name of the custom view must be.
3, AttributeSet and Typedarray
Consider the following:
There is a parameter in the construction method called AttributeSet
(Eg:mytextview (context context, AttributeSet attrs)) This parameter to see the name will know that contains the parameters of the collection, then I can not go through it to get my custom properties?
The first thing to AttributeSet
make sure is that all of the properties of the view declaration are stored, and that the outside can actually get the (custom) property, how do you do it?
Actually look at AttributeSet
the method to understand, the following look at the code.
Public Mytextview (Context context, AttributeSet attrs) { Super(context, attrs); int count = attrs.getattributecount (); for (int i = 0; i < count; i++) { = attrs.getattributename (i); = Attrs.getattributevalue (i); " Attrname = "+ Attrname +", Attrval = "+attrval); } // ==>use typedarray...}
Output:
MyTextView(4136): attrName = layout_width , attrVal = 100.0dipMyTextView(4136): attrName = layout_height , attrVal = 200.0dipMyTextView(4136): attrName = text , attrVal = helloworldMyTextView(4136): attrName = testAttr , attrVal = 520
Combined with the above layout file, what did you find?
I rubbed it, and it really was magical, and actually got all the properties, well, yes, by AttributeSet
getting the key and value of all the properties defined in the layout file (there are some ways to try it yourself), then is it typedarray that the ghost can be discarded? The answer is: NO!
.
Now focus on the next question:
What the hell is Typedarray? From where do you want me to use it?
We simply modify the properties of the Mytextview under the layout file.
< com . Example.test.MyTextView android:layout_width= "@dimen/dp100" Android:layout_ Height= "@dimen/dp200" zhy:testattr= "520" zhy:text= " @string/hello_world "/>
The result of running again now is:
MyTextView(4692): attrName = layout_width , attrVal = @2131165234MyTextView(4692): attrName = layout_height , attrVal = @2131165235MyTextView(4692): attrName = text , attrVal = @2131361809MyTextView(4692): attrName = testAttr , attrVal = 520>>use typedarrayMyTextView(4692): text = Hello world! , textAttr = 520
What did you find out? By AttributeSet
getting the value, if it is a reference, it becomes a string of @+ numbers. You say, can you read this thing? So you look at the last line using Typedarray to get the value, is not an instant to understand what.
TypedArray
is actually used to simplify our work, such as the above example, if the value of the property in the layout is a reference type (for example: @dimen/dp100), if use AttributeSet
to get the final pixel value, then the first step to get the ID, the second step to resolve the ID. And Typedarray is helping us simplify this process.
Paste: If you AttributeSet
get the final pixel value through the process:
int widthDimensionId = attrs.getAttributeResourceValue(0, -1);Log.e(TAG, "layout_width= "+getResources().getDimension(widthDimensionId));
OK, now people ask you typedarray the meaning of existence, you can tell him.
4, Declare-styleable
We have solved two problems, next, we look at the layout file, we have a property called: zhy:text
.
It is well known that the system provides a property called: android:text
, then I feel direct use of the android:text
more nice, so, consider the question:
If the system already has a semantically more explicit attribute, can I use it directly?
The answer is yes, how do you do it?
Use attributes directly in Attrs.xml android:text
.
<name= "Test"> <name= " Android:text "/> <name=" Testattr " Format= "integer"/></declare-styleable>
Note that here we use the already defined properties and do not need to add format
attributes (note the difference between the declaration and the use, the difference is that there is no format).
You can then get this in the class: The ta.getString(R.styleable.test_android_text)
layout file is straightforward android:text="@string/hello_world"
.
The properties defined in the system are, in fact, similar to the way we customize properties, where you can sdk/platforms/android-xx/data/res/values
see the properties defined in the system. You can then find the code that Typedarray gets the property in the system-provided view (Eg:textview) Construction method (take a look at it yourself).
Ok, next, I was thinking, since declare-styleable
the name of the label can be casually written, so casual, then consider the question:
What is the meaning of styleable? Can you not write? I custom attribute, I declare the attribute is good, why must write a styleable?
Really can not write, how to do it?
- First remove the declare-styleable label
So now the Attrs.xml is:
<? XML version= "1.0" encoding= "Utf-8" ?> < Resources > < name= "testattr" format= "integer"/></ Resources>
* Mytextview Implementation
Packagecom.example.test;ImportAndroid.content.Context;ImportAndroid.content.res.TypedArray;ImportAndroid.util.AttributeSet;ImportAndroid.util.Log;ImportAndroid.view.View; Public classMytextviewextendsView {Private Static FinalString TAG = Mytextview.class. Getsimplename (); Private Static Final int[] MattR ={Android. R.attr.text, r.attr.testattr}; Private Static Final intAttr_android_text = 0; Private Static Final intAttr_testattr = 1; PublicMytextview (Context context, AttributeSet attrs) {Super(context, attrs); //==>use TypedarrayTypedArray TA =context.obtainstyledattributes (Attrs, mattr); String text=ta.getstring (Attr_android_text); intTextattr = Ta.getinteger (attr_testattr, 1); //output Text = Hello world!, textattr = 520LOG.E (TAG, "text =" + text + ", textattr =" +textattr); Ta.recycle (); }}
Looks like some code, you can see that we declare an int array, the element in the array is the ID of the attr we want to get. And we define some shaped constants to represent their subscripts based on the position of the elements in the array, and then get through them TypedArray
.
Can see that our original:
R.styleable.test => mAttrR.styleable.test_text => ATTR_ANDROID_TEXT(0)R.styleable.test_testAttr => ATTR_TESTATTR(1)
So what, actually? Android will do the same in its own way, according to the traditional notation, which generates the following code in R.java:
Public Static Final classattr { Public Static Final intTestattr=0x7f0100a9;} Public Static Final classstyleable { Public Static Final intTest_android_text = 0; Public Static Final intTest_testattr = 1; Public Static Final int[] Test = { 0x0101014f, 0X7F0100A9 };}
OK, according to the above you should find out what. The Styleale system allows us to write a number of constants (int[] arrays, subscript constants) and so on, simplifying our development efforts (think about what kind of code you would write if you had a bunch of properties that you wrote your own constants). The declare-styleable
Name property, which is certainly known to all, is usually written in the class name of our custom view. Primarily for intuitive expression, this declare-styleable
attribute is used to change the view.
In fact, it is useful to understand this principle, see: Android Custom Controls elegantly implement split lines between elements
OK, now 5 questions, answered 4, the first question:
How does a few steps of a custom attribute work?
Well, the above and basically covers the answer to this question, everyone summarizes, so: a little.
Summarize today's blog.
- The declare-styleable and item,android inside the attrs.xml will make it easy for us to use (AAPT dry) based on the constants they generate in R.java, essentially, We can not declare that declare-styleable only declares the required properties.
- In the view construction method, we can get the
AttributeSet
value of the custom attribute, but it is troublesome, and TypedArray
it is convenient for us to get it.
- When we customize the view, we can use the properties already defined by the system.
*android Custom View Custom properties