一、簡述
隨著android的不斷演習(xí)辆布,必然不可免的接觸到了自定義View,自定義View顯然也是android知識中的重大重組部分,本篇將帶領(lǐng)大家走進(jìn)第一個自定義的View控件的實現(xiàn)饭望,TextView作為基礎(chǔ)控件之一,相信大家都很熟悉了形庭,現(xiàn)在我們就來簡單的實現(xiàn)一個TextView杰妓。
沒有基礎(chǔ)的同學(xué)可以先看這自定義View簡介
二、現(xiàn)在我們來實現(xiàn)TextView
1碘勉、先在values新建一個attrs.xml,然后配置自定義View的屬性桩卵,
<declare-styleable name="ViewText">
<attr name="mtext" format="string"/>
<attr name="mTextSize" format="dimension"/>
<attr name="mTextColor" format="color"/>
</declare-styleable>
分別定義了文本验靡,大小倍宾,跟顏色,屬性命名盡量不要跟原生的重復(fù)胜嗓,否則可能會報錯
2高职、新建ViewText繼承View,實現(xiàn)其構(gòu)造方法,三個構(gòu)造方法調(diào)用時機(jī)分別時辞州,在代碼中怔锌、在布局中、布局中引用style屬性時
public class MyTextView extends View {
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
我們在自定義View時也可以這樣寫
public class MyTextView extends View {
public MyTextView(Context context) {
super(context,null);
}
public MyTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs,0);
}
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
讓他層層調(diào)用变过,這樣最終都會執(zhí)行第三個構(gòu)造方法
3埃元、在布局中使用自定義的View
<com.example.mystudy.MyTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:mtext="這是自定義的View"
app:mTextColor="@color/colorAccent"
app:mSize="15dp"
/>
4、獲取屬性
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.MyTextView);
mText = typedArray.getString(R.styleable.MyTextView_mtext);
mTextColor = typedArray.getColor(R.styleable.MyTextView_mtext,mTextColor);
mTextSize = typedArray.getDimensionPixelSize(R.styleable.MyTextView_mtext,mTextSize);
typedArray.recycle();
到了這媚狰,我們就完成了自定義View的屬性設(shè)置到獲取了
5岛杀、現(xiàn)在到了,自定義View都會接觸到的方法onMeasure崭孤、 onDraw类嗤,在onMeasure方法中我們需要自己實現(xiàn)控件的寬高的測量
//獲得測量模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//獲得測量的大小
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
//如果寬高設(shè)置為wrap_content,則需要自行測量
if(widthMode == MeasureSpec.AT_MOST){
//矩形
Rect rect = new Rect();
//測量大小
paint.getTextBounds(mText,0,mText.length(),rect);
width = rect.width();
}
if(heightMode == MeasureSpec.AT_MOST){
Rect rect = new Rect();
paint.getTextBounds(mText,0,mText.length(),rect);
height = rect.height();
}
setMeasuredDimension(width,height);
后面我們就來到onDraw方法,繪制文本還涉及到一個基線的問題辨宠,已給出計算基線方式
Paint.FontMetricsInt f =paint.getFontMetricsInt();
int dy = (f.top-f.bottom)/2 - f.top;
int BaseLine = getHeight()/2+dy;
canvas.drawText(mText,0,BaseLine,paint);
完整代碼:
public class MyTextView extends View {
public MyTextView(Context context) {
this(context,null);
}
private String mText;
private int textSize = 15;
private int mColor = Color.BLACK;
private Paint paint;
public MyTextView(Context context, @Nullable AttributeSet attrs) {
this (context, attrs,0);
}
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray tppeArray = context.obtainStyledAttributes(attrs,R.styleable.MyTextView);
mText = tppeArray.getString(R.styleable.MyTextView_mtext);
textSize = tppeArray.getDimensionPixelSize(R.styleable.MyTextView_mTextSize,15);
mColor = tppeArray.getColor(R.styleable.MyTextView_mTextColor,mColor);
tppeArray.recycle();
paint = new Paint();
paint.setColor(mColor);
paint.setTextSize(textSize);
paint.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//獲得測量模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//獲得測量的大小
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
//如果寬高設(shè)置為wrap_content,則需要自行測量
if(widthMode == MeasureSpec.AT_MOST){
//矩形
Rect rect = new Rect();
//測量大小
paint.getTextBounds(mText,0,mText.length(),rect);
width = rect.width();
}
if(heightMode == MeasureSpec.AT_MOST){
Rect rect = new Rect();
paint.getTextBounds(mText,0,mText.length(),rect);
height = rect.height();
}
setMeasuredDimension(width,height);
}
@Override
protected void onDraw(Canvas canvas) {
Paint.FontMetricsInt f =paint.getFontMetricsInt();
int dy = (f.top-f.bottom)/2 - f.top;
int BaseLine = getHeight()/2+dy;
canvas.drawText(mText,0,BaseLine,paint);
}
}