Hello, everyone, I am programmer Double wood L, the follow-up will send special class article, this is the first custom control, after will also update related articles, welcome to pay attention to.
Custom attributes in the process of custom control belongs to a common operation, we can recall such a scene: in the process of custom view, we need to set different text sizes in different circumstances, so we need to provide external methods to set, so that more flexible operation. And our custom external method, is our custom attributes, then we analyze its principle and effect.
Here are some examples to analyze:
1. Create attrs. XML file in res->values. This file is used to declare the attribute name and the data format it accepts.
<? xml version="1.0" encoding="utf-8"? > <resources> <attr name="view_int" format="integer" />
<attr name="view_str" format="string" />
<attr name="view_bool" format="boolean" />
<attr name="view_color" format="color" />
<attr name="view_ref" format="reference" />
<attr name="view_float" format="float" />
<attr name="view_dim" format="dimension" />
<attr name="view_frac" format="fraction" />
<attr name="view_enum">
<enum name="num_one" value="1" />
<enum name="num_two" value="2" />
<enum name="num_three" value="3" />
<enum name="num_four" value="4" />
</attr>
<attr name="view_flag">
<flag name="top" value="0x1" />
<flag name="left" value="0x2" />
<flag name="right" value="0x3" />
<flag name="bottom" value="0x4" />
</attr>
</resources>
Copy the code
Attr noun analysis:
Name stands for the attribute name, which I defined myself.
Format Indicates the accepted input format. The formats are as follows:
Color: color value;boolean: Boolean value; -Leonard: Well, note that if it's dp then it's going to do the pixel conversion;float: floating point value; Integer: integer value; String: string. 3. fractionenum: enumerated values; Flag: it is self-defined, that is, it corresponds to its own attribute value; Reference: refers to other resources; The reference | color: color resource file; reference|boolean: Resource file with Boolean value.Copy the code
2, the use of custom attributes, here we use two ways to compare and analyze
The most primitive way to use it
(1) User-defined files are as follows:
public class TestAttrsView extends View {
private final String TAG = "TestAttrsView:";
public TestAttrsView(Context context) {
this(context, null);
}
public TestAttrsView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public TestAttrsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// The original usage
for (int i = 0; i < attrs.getAttributeCount(); i++) {
Log.i(TAG, "name:" + attrs.getAttributeName(i) + " value:"+ attrs.getAttributeValue(i)); }}}Copy the code
AttributeSet, the parameter to the TestAttrsView method, is an XML parsing utility class that helps us extract attribute names and attribute values from the layout XML.
(2) Use in layout file XML
<? xml version="1.0" encoding="utf-8"? > <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.viewdemo.customView.TestAttrsView
android:layout_width="200dp"
android:layout_height="200dp"
app:view_bool="true"
app:view_color="#e5e5e5"
app:view_dim="10px"
app:view_float="5.0"
app:view_frac="100%"
app:view_int="10"
app:view_ref="@dimen/dp_15"
app:view_str="test attrs view" />
</FrameLayout>
Copy the code
To use custom attributes here, you need to declare the namespace of XML, where APP is the namespace used to precede the custom attributes.
XMLNS: app = “schemas.android.com/apk/res-aut…” Declare XML namespaces, XMLNS stands for “XML namespace”. The colon is followed by the alias given to the reference. Schemas are one of the two constraint files of XML documents. They specify what elements (tags) are in XML, what attributes the elements have, and the relationships between the elements. Of course, understanding Schemas from an object-oriented perspective, they can be considered as “classes” or “templates” of constrained XML documents.
(3) Print the result of the attribute name and value as follows:
AttributeSet prints out all the attributes in the layout file XML, which a careful child might have noticed:
XML file: app:view_ref="@dimen/dp_15"The following output is displayed: name:view_ref value:@2131034213
Copy the code
This property is set to an integer size, and the last print is the resource number.
So what if we want to print the integer size that we set?
This is where the main character of our article comes in, using TypedArray.
- Use TypedArray mode
(1) We need to modify attrs. XML with the “register-styleable” tag as follows:
<? xml version="1.0" encoding="utf-8"? > <resources> <declare-styleable name="TestStyleable">
<attr name="view_int" format="integer" />
<attr name="view_str" format="string" />
<attr name="view_bool" format="boolean" />
<attr name="view_color" format="color" />
<attr name="view_ref" format="reference" />
<attr name="view_float" format="float" />
<attr name="view_dim" format="dimension" />
<attr name="view_frac" format="fraction" />
<attr name="view_enum">
<enum name="num_one" value="1" />
<enum name="num_two" value="2" />
<enum name="num_three" value="3" />
<enum name="num_four" value="4" />
</attr>
<attr name="view_flag">
<flag name="top" value="0x1" />
<flag name="left" value="0x2" />
<flag name="right" value="0x3" />
<flag name="bottom" value="0x4" />
</attr>
</declare-styleable>
</resources>
Copy the code
As you can see from the attrs file, we attribute declarations to TestStyleable, which means they belong to TestStyleable.
(2) Attribute analysis:
public class TestAttrsView extends View {
private final String TAG = "TestAttrsView:";
public TestAttrsView(Context context) {
this(context, null);
}
public TestAttrsView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public TestAttrsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// The original usage
/* for (int i = 0; i < attrs.getAttributeCount(); i++) { Log.i(TAG, "name:" + attrs.getAttributeName(i) + " value:" + attrs.getAttributeValue(i)); } * /
// Use TypeArray mode
/ / R.s tyleable TestStyleable refers to want to parse attributes
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TestStyleable);
int integerView = typedArray.getInt(R.styleable.TestStyleable_view_int, 0);
Log.i(TAG, "name:view_int" + " value:" + integerView);
boolean aBooleanView = typedArray.getBoolean(R.styleable.TestStyleable_view_bool, false);
Log.i(TAG, "name:view_bool" + " value:" + aBooleanView);
int colorView = typedArray.getColor(R.styleable.TestStyleable_view_color, Color.WHITE);
Log.i(TAG, "name:view_color" + " value:" + colorView);
String stringView = typedArray.getString(R.styleable.TestStyleable_view_str);
Log.i(TAG, "name:view_str" + " value:" + stringView);
float refView = typedArray.getDimension(R.styleable.TestStyleable_view_ref, 0);
Log.i(TAG, "name:view_ref" + " value:" + refView);
float aFloatView = typedArray.getFloat(R.styleable.TestStyleable_view_float, 0);
Log.i(TAG, "name:view_float" + " value:" + aFloatView);
float dimensionView = typedArray.getDimension(R.styleable.TestStyleable_view_dim, 0);
Log.i(TAG, "name:view_dim" + " value:" + dimensionView);
float fractionView = typedArray.getFraction(R.styleable.TestStyleable_view_frac, 1.1.0);
Log.i(TAG, "name:view_frac" + " value:" + fractionView);
//typedArray is stored in the cache pool, which needs to be freed when usedtypedArray.recycle(); }}Copy the code
Here I just print out the results of the parsing directly, and here WE can get the custom properties we want, while the system’s properties can be ignored.
(3) The running results are as follows
From the result of parsing, we can see that the size result has been converted to the actual value:
XML file: app:view_ref="@dimen/dp_15"Name :view_ref value:41.25
Copy the code
At this time, some children asked again, I set 15DP, why the final print is 41.25? In fact, the parsed value is px, so this output is the converted value.
This method is used in the parsing process:
context.obtainStyledAttributes(attrs, R.styleable.TestStyleable);
Copy the code
Let’s take a look at the source of this method:
public final TypedArray obtainStyledAttributes(
@Nullable AttributeSet set, @NonNull @StyleableRes int[] attrs) {
return getTheme().obtainStyledAttributes(set, attrs, 0.0);
}
Copy the code
We can see from the source that this method takes two parameters:
AttributeSet set: A collection of attributes that represents the current XML declarationint[] attrs: indicates the attributes you want to select. If you want any attributes, you can write them to thisintIn the arrayCopy the code
The obtainStyledAttributes method returns a value of TypedArray. This type records the collection of fetched attribute values that can be found by subscripting the array. Index subscript by R.s tyleable TestStyleable_xx access, “xx” said property name, generally named “styleable name” + “_” + “attribute name”.
TypedArray provides various apis, such as getInteger, getString, getDimension, etc., to obtain attribute values. These methods all need to pass in the index of the position of the attribute name in the int array obtainStyledAttributes. Get the value of the property in the array by subscript.
The TypedArray function is a resource mapping function, mapping custom attributes in XML Settings to class values, so that it is easy to obtain.
Here is the analysis finished!