Android 之自定義View


坐標系說明:



View的坐標系:


image.png

實現(xiàn)流程:
主要方法onMeasure()植阴、onLayout()盖呼、onDraw();
1、View的構(gòu)造方法的重載
public class MyView  extends View {
    private String TAG="MyView";
//重載View的構(gòu)造函數(shù)
//一般在直接New一個View的時候調(diào)用
    public MyView(Context context) {
        super(context);
        Log.d(TAG,"======MyView1");
    }
//一般在layout文件中使用的時候會調(diào)用,關(guān)于它的所有屬性(包括自定義屬性)都會包含在attrs中傳遞進來。
    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        Log.d(TAG,"======MyView2");
    }
//由于三個參數(shù)的構(gòu)造函數(shù)第三個參數(shù)一般不用,暫不考慮
    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        Log.d(TAG,"======MyView3");
    }
 //有四個參數(shù)的構(gòu)造函數(shù)在API21的時候才添加上,暫不考慮
    /*public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }*/

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d(TAG,"======onDraw");
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        Log.d(TAG,"======onLayout");
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.d(TAG,"======onMeasure");
    }
}

在布局文件中引用當前view:

<com.wtt.testac.custom.MyView
android:layout_width="match_parent"
android:layout_height="match_parent" />

打印的結(jié)果:



結(jié)論:在布局文件中調(diào)用的構(gòu)造方法是兩個參數(shù)的構(gòu)造方法终惑。為什么方法會被多次調(diào)用?因為view繪制過程中為了確認view大小声登,會多次重復(fù)調(diào)用onMeasure狠鸳。

2揣苏、構(gòu)造方法接下來調(diào)用onMeasure()方法來測量View的大小
View的大小不僅由自身所決定,同時也會受到父控件的影響件舵,為了我們的控件能更好的適應(yīng)各種情況卸察,一般會自己進行測量。

//計算view高度寬度大小
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.d(TAG,"======onMeasure");
        //測量View大小

        int width=MeasureSpec.getSize(widthMeasureSpec);//測量寬度的大小
        int width_mode=MeasureSpec.getMode(widthMeasureSpec);//取出寬度的測量模式

        Log.d(TAG,"width==="+width);
        Log.d(TAG,"width_mode==="+width_mode);

        int height=MeasureSpec.getSize(heightMeasureSpec);//測量高度的大小
        int height_mode=MeasureSpec.getMode(heightMeasureSpec);//取出高度的測量模式

        Log.d(TAG,"height==="+height);
        Log.d(TAG,"height_mode==="+height_mode);

    }

從上面可以看出 onMeasure 函數(shù)中有 widthMeasureSpec 和 heightMeasureSpec 這兩個 int 類型的參數(shù)铅祸,它們是和寬高相關(guān)的坑质, 但它們其實不是寬和高, 而是由寬临梗、高和各自方向上對應(yīng)的測量模式來合成的一個值涡扼。
在MeasureSpec當中一共存在三種mode:UNSPECIFIED、EXACTLY 和AT_MOST盟庞。



在測量之后吃沪,View的大小已經(jīng)確定,View的大小不僅由自身控制還受父布局的影響什猖,所以可以調(diào)用onSizeChanged()函數(shù)來確定View的大小票彪。

 //函數(shù)在視圖大小發(fā)生改變時調(diào)用
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
//參數(shù)分別是寬、高不狮、上一次寬降铸、上一次高
    }

3、調(diào)用onLayout()函數(shù)來設(shè)置View的位置摇零,一般情況下是在VIewGroup中會調(diào)用到推掸,調(diào)用了子View中的layout()函數(shù)。
在自定義ViewGroup中驻仅,onLayout一般是循環(huán)取出子View谅畅,然后經(jīng)過計算得出各個子View位置的坐標值。

  //計算view位置
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        Log.d(TAG,"======onLayout");
        //left   View左側(cè)距父View左側(cè)的距離
        //top    View頂部距父View頂部的距離
        //right  View右側(cè)距父View左側(cè)的距離
        //bottom View底部距父View頂部的距離

    }

4雾家、調(diào)用onDraw()函數(shù)繪制VIew
在onDraw()方法中有一個Canvas對象铃彰,稱之為畫布,可以在上面繪制各種東西芯咧。

//繪制View
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d(TAG,"======onDraw");
        //繪制顏色
        canvas.drawColor(Color.YELLOW);
    }

想要繪制內(nèi)容,需要一個Paint畫筆竹揍,然后就可以在Canvas畫布上繪制任何VIew了

//創(chuàng)建畫筆
    Paint paint=new Paint();
//在構(gòu)造方法中調(diào)用方法
    private void init(){
        paint.setColor(Color.BLACK);//設(shè)置畫筆顏色
        paint.setStyle(Paint.Style.STROKE);//設(shè)置畫筆為空心
        paint.setStrokeWidth(5f);//設(shè)置畫筆寬度
    }

繪制一個圓環(huán):

//cx圓心x坐標敬飒、cy圓心y坐標、radius半徑芬位、paint畫筆
canvas.drawCircle(150f,150f,50f,paint);

繪制矩形的幾種方法:

        // 第一種
        canvas.drawRect(100,100,500,300,paint);

        // 第二種
        Rect rect = new Rect(100,100,500,300);
        canvas.drawRect(rect,paint);

        // 第三種
        RectF rectF = new RectF(100,100,500,300);
        canvas.drawRect(rectF,paint);
image.png

這幾種方法繪制出來的View都是是一樣的无拗,Rect和RectF有什么區(qū)別呢,兩者最大的區(qū)別是精度不同昧碉,Rect是int(整形)的英染,而RectF是float(單精度浮點型)的揽惹。

總結(jié):以上是自定義view的基礎(chǔ)的相關(guān)的內(nèi)容,很多東西還是得自己親自手敲實踐四康,腳踏實地走過來才行搪搏。以后還會繼續(xù)完善本文的內(nèi)容,有不對的地方闪金,歡迎指出疯溺,會繼續(xù)努力。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哎垦,一起剝皮案震驚了整個濱河市囱嫩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌漏设,老刑警劉巖墨闲,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異郑口,居然都是意外死亡损俭,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門潘酗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杆兵,“玉大人,你說我怎么就攤上這事仔夺∷鲈啵” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵缸兔,是天一觀的道長日裙。 經(jīng)常有香客問我,道長惰蜜,這世上最難降的妖魔是什么昂拂? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮抛猖,結(jié)果婚禮上格侯,老公的妹妹穿的比我還像新娘。我一直安慰自己财著,他們只是感情好联四,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著撑教,像睡著了一般朝墩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上伟姐,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天收苏,我揣著相機與錄音亿卤,去河邊找鬼。 笑死鹿霸,一個胖子當著我的面吹牛粥烁,可吹牛的內(nèi)容都是我干的杨刨。 我是一名探鬼主播秃励,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼歪架,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了葛闷?” 一聲冷哼從身側(cè)響起憋槐,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎淑趾,沒想到半個月后阳仔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡扣泊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年近范,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片延蟹。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡评矩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出阱飘,到底是詐尸還是另有隱情斥杜,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布沥匈,位于F島的核電站蔗喂,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏高帖。R本人自食惡果不足惜缰儿,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望散址。 院中可真熱鬧乖阵,春花似錦、人聲如沸爪飘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽师崎。三九已至,卻和暖如春椅棺,著一層夾襖步出監(jiān)牢的瞬間犁罩,已是汗流浹背齐蔽。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留床估,地道東北人含滴。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像丐巫,于是被迫代替她去往敵國和親谈况。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容