Android自定義view-自繪View

dapan發表於2021-09-09

android自定義view一般分為三種

1.組合控制元件
2.自繪控制元件
3.繼承控制元件

今天主要分析下自繪控制元件。何為自繪控制元件,就是完全用Paint和canvas畫出來的,就是在onDraw()方法裡面繪畫,在onMeasure()方法裡面進行測量,在onLayout()方法中定位每個子元件。

還是舉個例子來的實際些,假如我們要畫一個最簡單的TextView,首先想到的就是canvas.drawText()方法,但還是得一步一步來。

(1)寫一個MyTextView類繼承View,重寫三個構造方法,當然還有onDraw()和onMeasure()方法

(2)接下來就要想既然是TextView,那肯定是有text,color,textSize等屬性。在values目錄下的attrs.xml中定義好這些屬性,以便在xml中引入MyTextView能夠直接操作這些值,然後在有三個引數的構造方法裡面將這些屬性與控制元件關聯,還是先貼程式碼來的直接些,如下

attrs.xml:


    

到現在其實我們的畫的MyTextView已經可以用了,額?不是還有一個onMeasure方法什麼都沒有寫嗎,不急我們先在xml中引入試試看效果



    

圖片描述
可以看到,我們設定textview的寬高都是wrap_content,但是執行之後都佔滿了螢幕,之前重寫的onMeasure方法就就派上用場了

1.首先要了解測量元件的寬高時,是由元件的父容器呼叫的,首先容器他會遍歷容器內所有的子元件,一個一個的測量寬高,這裡的我們自定義textView的父容器就是最外層RelativeLayout

2.然後要了解MeasureSpec類,這個類為我們提供了兩個方法,getMode(int measureSpec)和getSize(int measureSpec)可以獲得寬和高的尺寸和模式,這個類還為我們提供了三個常量MeasureSpec.EXACTLY、MeasureSpec.AT_MOST、MeasureSpec.UNSPECIFIED
MeasureSpec.EXACTLY:已經為TextView指定確定尺寸或者為math_parent時
MeasureSpec.AT_MOST:當TextView為wrap_content時
MeasureSpec.UNSPECIFIED:TextView未定義寬高

上面我們設定了高為wrap_content,但是我們沒有測量textview的高,如果指定了為wrap_content,那麼此時的高應該是TextView本身的高,所以需要測量然後返回給父容器,下面我們重寫onMeasure方法

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int width = measureWidth(widthMeasureSpec);        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(width, height);

    }    private int measureWidth(int widthMeasureSpec){        int mode = MeasureSpec.getMode(widthMeasureSpec);        int size = MeasureSpec.getSize(widthMeasureSpec);        int width = 0;        if(mode == MeasureSpec.EXACTLY){            //如果是math_parent或確定尺寸
            width = size;
        }else if(mode == MeasureSpec.AT_MOST){            //如果是wrap_parent
            width = getPaddingLeft() + mBound.width() + getPaddingRight();
        }        return width;

    }    private int measureHeight(int heightMeasureSpec){        int mode = MeasureSpec.getMode(heightMeasureSpec);        int size = MeasureSpec.getSize(heightMeasureSpec);        int height = 0;        if(mode == MeasureSpec.EXACTLY){            //如果是math_parent或確定尺寸
            height = size;
        }else if(mode == MeasureSpec.AT_MOST){            //如果是wrap_parent
            height = getPaddingTop() + mBound.height() + getPaddingBottom();
        }

[連結描述]()
        return height;
    }

現在TextView測量完成了,已經可以設定寬高了,寬高設定為wrap_content則是TextView本身的寬高,因為我們還考慮了Padding,所以也可以設定TextView的Padding,如果測量時沒考慮Padding在xml中設定是不起作用的,有興趣的的可以試一試

當然,這只是一個很簡單的自定義TextView元件,僅為簡單的理解自繪View,另外還有自定義容器,自定義容器時就要考慮onLayout方法了,因為要定位每個子元件在容器中位置。想要熟練使用自定義View,必須熟練使用Paint和canvas,這是自定義View的基本

有興趣的可以移至

原文連結:http://www.apkbus.com/blog-842132-77090.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/758/viewspace-2812482/,如需轉載,請註明出處,否則將追究法律責任。

相關文章