自定義屬性


有以下幾個步驟:

自定義一個CustomView(extends View )類
編寫values/attrs.xml,在其中編寫styleable和item等標簽元素
在布局文件中CustomView使用自定義的屬性(注意namespace)
在CustomView的構造方法中通過TypedArray獲取
自定義屬性的聲明文件,在res/values 目錄下新建一個 attrs.xml文件
如要用系統定義過的android:text"屬性,不需要寫format
可以看一下系統中自定義屬性的文件 Sdk/platforms/android-xx/data/res/values/attrs.xml

有多個styleable都要用到的共同的屬性,在resources開頭進行定義,后續引用只需要引用名字就可以了
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="textColor" format="color"/>
<attr name="textSize" format="dimension"/>
1
2
3
4
使用系統原有的屬性時,在前面加上android命名
<declare-styleable name="title_attrs">
<!--尺寸值,格式是dimension-->
<attr name="width" format="dimension"/>
<attr name="height" format="dimension"/>
<attr name="textColor"/>
<attr name="textSize"/>
<!--聲明需要使用系統定義過的text屬性,注意前面需要加上android命名-->
<attr name="android:text"/>
</declare-styleable>

<declare-styleable name="RectangleView">
<attr name="textColor"/>
<attr name="textSize"/>
<attr name="android:text"/>
</declare-styleable>

</resources>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在布局文件中對應的去用
首先需要加上一個命名空間xmlns:title="http://schemas.android.com/apk/res-auto"
然后直接利用這個命名空間title設置屬性即可
<com.sky.customapplication.TitleView
android:id="@+id/title_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
title:textColor="#000"
title:textSize="26sp"
android:text="im text">

</com.sky.customapplication.TitleView>
1
2
3
4
5
6
7
8
9
在自定義控件代碼中獲取各屬性
R.styleable.RectangleView是剛剛attrs文件中的name

TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RectangleView, defStyleAttr, 0);
//mText = array.getString(R.styleable.RectangleView_android_text);
mTextColor = array.getColor(R.styleable.RectangleView_textColor, Color.BLACK);
mTextSize = array.getDimensionPixelSize(R.styleable.RectangleView_textSize, 40);
array.recycle(); //注意回收
1
2
3
4
5
onDraw()
實現三個構造方法,在第三個構造方法中進行初始化、解析自定義屬性的值
初始化筆刷,mBounds是繪制時控制文本繪制范圍的長方形
public class RectangleView extends View implements View.OnClickListener {

private Paint mPaint;
private Rect mBounds;
//private String mText;
private float mTextSize;
private int mTextColor;
private int mCount;
private String text;

public RectangleView(Context context) {
this(context, null);
}

public RectangleView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public RectangleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//新建畫筆
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //抗鋸齒
mBounds = new Rect();

//加載自定義屬性集合
TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RectangleView, defStyleAttr, 0);
// 將解析的屬性傳入到畫筆顏色變量當中(本質上是自定義畫筆的顏色)
// 第二個參數是默認設置顏色(即無指定color情況下使用)
//mText = array.getString(R.styleable.RectangleView_android_text);
mTextColor = array.getColor(R.styleable.RectangleView_textColor, Color.BLACK);
mTextSize = array.getDimensionPixelSize(R.styleable.RectangleView_textSize, 40);

array.recycle(); //記得回收

setOnClickListener(this);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
在onDraw中繪制
@Override
protected void onDraw(Canvas canvas) {
//畫筆顏色
mPaint.setColor(Color.YELLOW);
//畫一個長方形
canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
//設置畫字的顏色
mPaint.setColor(mTextColor);
mPaint.setTextSize(mTextSize);
text = String.valueOf(mCount);
mPaint.getTextBounds(text, 0, text.length(), mBounds);
float textWidth = mBounds.width();
float textHeight = mBounds.height();
//文字繪制的起點是從文字的左下角開始的,實際看見文字的Y坐標需要加上文字的自身高度
canvas.drawText(text, getWidth()/2 - textWidth/2, getHeight()/2 + textHeight/2, mPaint);
}

@Override
public void onClick(View v) {
mCount++;
invalidate(); //視圖重繪,onDraw調用
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
在布局中引用
<com.sky.customapplication.RectangleView
android:layout_width="200dp"
android:layout_height="100dp"
title:textColor="#00FF33"
title:textSize="30sp"
android:padding="15dp"
/>
1
2
3
4
5
6
7


手動支持wrap_content屬性
但是此時,如果設置layout_width和layout_height 屬性為 wrap_content,並不會適應自身大小,而是填滿父控件,和match_parent效果相同。
這是因為使用系統的onMeasure方法時,系統幫我們測量的高度和寬度都是MATCH_PARNET,當我們設置明確的寬度和高度時,系統幫我們測量的結果就是我們設置的結果;而當我們設置為WRAP_CONTENT系統幫我們測量的結果也是MATCH_PARENT的長度。
所以,當設置了WRAP_CONTENT時,我們需要自己進行測量,即重寫onMesure方法:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM