android自定義View的開篇,實現簡單的TextView

一、簡述

隨着android的不斷演習,必然不可免的接觸到了自定義View,自定義View顯然也是android知識中的重大重組部分,本篇將帶領大家走進第一個自定義的View控件的實現,TextView作爲基礎控件之一,相信大家都很熟悉了,現在我們就來簡單的實現一個TextView。

沒有基礎的同學可以先看這自定義View簡介

二、現在我們來實現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>

分別定義了文本,大小,跟顏色,屬性命名儘量不要跟原生的重複,否則可能會報錯

2、新建ViewText繼承View,實現其構造方法,三個構造方法調用時機分別時,在代碼中、在佈局中、佈局中引用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);
    }
}

讓他層層調用,這樣最終都會執行第三個構造方法

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的屬性設置到獲取了

5、現在到了,自定義View都會接觸到的方法onMeasure、 onDraw,在onMeasure方法中我們需要自己實現控件的寬高的測量

        //獲得測量模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        //獲得測量的大小
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        //如果寬高設置爲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);
        //如果寬高設置爲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);
    }
}

簡書地址:android自定義View的開篇,實現簡單的TextView

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章