Reference resources: http://blog.csdn.net/jiaoyang623/article/details/7790494
Preface
_When the given widget can not meet the needs of user-defined, it is very convenient to configure view with xml, if we want to pass parameters to view through xml, we have to write more things.
The following example is an extension of TextView. TextView provides the function of setting four orientation pictures, but it can not set the size of pictures and text spacing. This paper implements a new class TextViewPlus, which extends TextView to configure the size of pictures and text spacing in xml.
_Changing image size cannot be done in xml, but can be done in Java code. Drawable [], the four directions around the text, is first obtained, then drawable.setBounds() is called to set the size, and then put back into TextView. Then the problem is how to get the class to read the information in xml.
Implementation of Control
The code is divided into three parts:
1. activity_main.xml layout file;
2. TextViewPlus class;
3. attrs.xml file, which allows the system to identify custom attributes.
The order of construction should be attrs. XML - > TextViewPlus. Java - > activity_main. XML
Configuration file attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TextViewPlus">
<attr name="left_height" format="dimension" />
<attr name="left_width" format="dimension" />
<attr name="right_height" format="dimension" />
<attr name="right_width" format="dimension" />
<attr name="top_height" format="dimension" />
<attr name="top_width" format="dimension" />
<attr name="bottom_height" format="dimension" />
<attr name="bottom_width" format="dimension" />
</declare-styleable>
</resources>
Interpretation: attrs.xml is placed in res/values. The name of line 4 needs to specify the class that uses the parameters. Lines 5 to 12 need to set the parameters in the layout file. Name is the name, format is the data type, and the system will automatically generate the variables in the R file.
Class TextViewPlus
package com.john.textviewplus;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* TextView with drawable size can be set
* Created by john on 17-1-3.
*/
public class TextViewPlus extends TextView {
// Width and height of images in all directions that need to be read from xml
private int leftHeight = -1;
private int leftWidth = -1;
private int rightHeight = -1;
private int rightWidth = -1;
private int topHeight = -1;
private int topWidth = -1;
private int bottomHeight = -1;
private int bottomWidth = -1;
public TextViewPlus(Context context) {
super(context);
}
public TextViewPlus(Context context, AttributeSet attrs) {
super(context, attrs);
// super must be configured before our code
init(context, attrs, 0);
}
public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// super must be configured before our code
init(context, attrs, defStyle);
}
/**
* Initialize read parameters
* */
private void init(Context context, AttributeSet attrs, int defStyle) {
// TypeArray contains the parameters we need to use
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.TextViewPlus, defStyle, 0);
if (a != null) {
// Get the number of parameters
int count = a.getIndexCount();
int index = 0;
// Traversal parameters. First read index from TypedArray.
// The resulting index corresponds to the number of parameter names set in attrs.xml compiled in R
// Here you get the width and height in all directions.
for (int i = 0; i < count; i++) {
index = a.getIndex(i);
if (index == R.styleable.TextViewPlus_bottom_height) {
bottomHeight = a.getDimensionPixelSize(index, -1);
} else if (index == R.styleable.TextViewPlus_bottom_width) {
bottomWidth = a.getDimensionPixelSize(index, -1);
} else if (index == R.styleable.TextViewPlus_left_height) {
leftHeight = a.getDimensionPixelSize(index, -1);
} else if (index == R.styleable.TextViewPlus_left_width) {
leftWidth = a.getDimensionPixelSize(index, -1);
} else if (index == R.styleable.TextViewPlus_right_height) {
rightHeight = a.getDimensionPixelSize(index, -1);
} else if (index == R.styleable.TextViewPlus_right_width) {
rightWidth = a.getDimensionPixelSize(index, -1);
} else if (index == R.styleable.TextViewPlus_top_height) {
topHeight = a.getDimensionPixelSize(index, -1);
} else if (index == R.styleable.TextViewPlus_top_width) {
topWidth = a.getDimensionPixelSize(index, -1);
}
}
// Get the pictures in all directions and store them in the array in the order of left-up-right-down.
Drawable[] drawables = getCompoundDrawables();
int dir = 0;
// 0-left; 1-top; 2-right; 3-bottom;
for (Drawable drawable : drawables) {
// Set Picture Size
setImageSize(drawable, dir++);
}
// Place the picture back in TextView
setCompoundDrawables(drawables[0], drawables[1], drawables[2],
drawables[3]);
}
}
/**
* Set the size of the picture
* */
private void setImageSize(Drawable d, int dir) {
if (d == null) {
return;
}
int height = -1;
int width = -1;
// Assignment of width and height according to direction
switch (dir) {
case 0:
// left
height = leftHeight;
width = leftWidth;
break;
case 1:
// top
height = topHeight;
width = topWidth;
break;
case 2:
// right
height = rightHeight;
width = rightWidth;
break;
case 3:
// bottom
height = bottomHeight;
width = bottomWidth;
break;
}
// If there is no set value for the width or height of a direction, do not set the image size.
if (width != -1 && height != -1) {
d.setBounds(0, 0, width, height);
}
}
}
Interpretation: The reading of TypedArray is the main part. You can think of TypedArray as a Map < Integer key, Object value > and get each value by traversing the key. The value of this key is written in R.stylable, and value needs to be read by getDimensionPixelSize() and other methods, which is somewhat similar to calling the database to read data from cursor.
Layout file activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.john.textviewplus.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white">
<com.john.textviewplus.TextViewPlus
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableLeft="@drawable/bg_round_rectangle_white"
android:gravity="center_vertical"
android:drawablePadding="8dp"
android:text="State one"
android:textColor="#FF4A4A4A"
android:textSize="13sp"
app:left_height="16dp"
app:left_width="16dp"/>
<com.john.textviewplus.TextViewPlus
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableLeft="@drawable/bg_round_rectangle_white_dash"
android:gravity="center_vertical"
android:drawablePadding="8dp"
android:text="Status two"
android:textColor="#FF4A4A4A"
android:textSize="13sp"
app:left_height="16dp"
app:left_width="16dp"/>
<com.john.textviewplus.TextViewPlus
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableLeft="@drawable/bg_round_rectangle_red"
android:gravity="center_vertical"
android:drawablePadding="8dp"
android:text="Status three"
android:textColor="#FF4A4A4A"
android:textSize="13sp"
app:left_height="16dp"
app:left_width="16dp"/>
<com.john.textviewplus.TextViewPlus
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableLeft="@drawable/bg_round_rectangle_green"
android:gravity="center_vertical"
android:drawablePadding="8dp"
android:text="Status four"
android:textColor="#FF4A4A4A"
android:textSize="13sp"
app:left_height="16dp"
app:left_width="16dp"/>
</LinearLayout>
</RelativeLayout>
Interpretation:
- Line 3 xmlns:app= "http://schemas.android.com/apk/res-auto" is used to declare that I need to use the properties defined by the project itself.
- app:left_height, app:left_width uses attributes, which are attributes defined in attrs.xml.
- App and app:left_height in xmlns:app and app:left_height in app:left_width are corresponding. The name can be changed arbitrarily as long as it is not a keyword.