Android群英傳讀書筆記--第3章Android控件架構(gòu)與自定義控件詳解

個人讀書筆記,部分沒讀懂的知識點(diǎn)可能會簡單概括或缺失,以后反復(fù)閱讀后再完善。

第3章 Android控件架構(gòu)與自定義控件詳解

3.1 Android 控件結(jié)構(gòu)

Android控件大致分為兩類:ViewGroup控件與View控件。

通過ViewGroup控件,界面上的控件形成一個樹形結(jié)構(gòu)(控件樹)。

上層控件負(fù)責(zé)下層控件的測量與繪制,并傳遞交互事件。
Activity的findViewById()方法,就是在控件樹中以樹的深度優(yōu)先遍歷查找對應(yīng)元素。

ViewParent 是整個控件樹的核心。

View樹.jpg

Activity使用setContentView()方法來把整個DecorView添加到PhoneWindow中。

UI結(jié)構(gòu).jpg

3.2 View的測量

Android通過MeasureSpec類測量View,有三種測量模式:

·EXACTLY

精確模式,比如android:layout_width="100dp",使用的是EXACTLY模式(默認(rèn))。

·AT_MOST

最大值模式,比如wrap_content,只要不超過父控件允許的最大尺寸,控件大小隨內(nèi)容變化而變化。

·UNSPECIFIED

繪制自定義View時使用

View類默認(rèn)的onMeasure()只支持EXACTLY模式,所以自定義控件的時候最好重寫onMeasure()方法:

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(
                measureWidth(widthMeasureSpec),
                measureHeight(heightMeasureSpec)
        );
    }

    private int measureHeight(int heightMeasureSpec) {
        int result=0;
        int specMode=MeasureSpec.getMode(heightMeasureSpec);
        int specSize = MeasureSpec.getSize(heightMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result=specSize;
        }else {
            result=200;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    private int measureWidth(int widthMeasureSpec) {
        int result=0;
        int specMode=MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result=specSize;
        }else {
            result=200;
            if (specMode == MeasureSpec.AT_MOST) {
                //取最?。ú荒艹^父控件)
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

3.3 View的繪制

簡單介紹了Canvas對象。使用Canvas通常需要通過繼承View并重寫onDraw()方法。

在onDraw()方法里有一個canvas參數(shù),使用它就能繪圖。

在其他地方需要創(chuàng)建一個Canvas對象:

Canvas canvas = new Canvas(bitmip);

創(chuàng)建時傳一個bitmap對象時為了儲存使用繪制在Canvas上的像素信息。

3.4 ViewGroup的測量

ViewGroup通過遍歷子View的大小,從而決定自己的大小。

自定義ViewGroup,通常會取重寫onLayout()方法控制子View顯示位置的邏輯。
如果需要支持wrap_content屬性,它也像View一樣得去重寫onMeasure()方法。

3.5 ViewGroup的繪制

ViewGroup的onDraw()方法只會在指定背景顏色時調(diào)用。

ViewGroup使用dispatchDraw()方法來繪制子View,過程:遍歷->調(diào)用子View的繪制方法。

3.6 自定義View

View中比較重要的回調(diào)方法:

·onFinishInflate(): 從XML加載組件后回調(diào)。

·onSizeChanged(): 組件大小改變時回調(diào)。

·onMeasure(): 測量方法。

·onLayout(): 確定顯示的位置。

·onTouchEvent(): 監(jiān)聽觸摸事件。

有三種方法實(shí)現(xiàn)自定義的控件:

·對現(xiàn)有控件進(jìn)行拓展

書中演示了一個textView例子。

·創(chuàng)建復(fù)合控件

演示了一個TopBar控件。

·重寫View來實(shí)現(xiàn)全新的控件

演示了弧線展示圖和音頻條形圖。

3.7 自定義ViewGroup

自定義ViewGroup需要重寫onMeasure()方法來對子View進(jìn)行測量,重寫onLayout()方法來確定子View的位置,重寫onTouchEvent()方法增加響應(yīng)事件。

演示了一個類似ScrollView的自定義ViewGroup

3.8 事件攔截機(jī)制分析

如果一個觸摸事件,子View和父ViewGroup都有可能想處理,這就需要事件攔截。

在ViewGroup中,事件有三個方法:

·dispatchTouchEvent()

·onInterceptTouchEvent()

·onTouchEvent()

而View只有兩個方法:

·dispatchTouchEvent()

·onTouchEvent()

View比ViewGroup少了個onInterceptTouchEvent()方法,這個onInterceptTouchEvent()方法就是事件攔截的核心代碼。

事件傳遞時,先執(zhí)行dispatchTouchEvent()方法,再執(zhí)行onInterceptTouchEvent()方法。

事件處理時,都是執(zhí)行onTouchEvent()方法。

假設(shè)有三層結(jié)構(gòu),

最外層叫它MyViewGroupA,

第二層叫它MyViewGroupB,

最里層叫它MyView。

事件傳遞時,dispatchTouchEvent()方法一般不會去改寫,所以暫時不管。

則事件的傳遞過程:
MyViewGroupA -> onInterceptTouchEvent() A -> MyViewGroupB -> onInterceptTouchEvent() B -> MyView

事件的處理過程:
onTouchEvent() View -> onTouchEvent() B -> onTouchEvent() A

方法的返回值都是布爾值,初始情況下返回值都是false(都往下傳遞\往上處理)。

如果在MyViewGroupA的onInterceptTouchEvent()中返回true,則MyViewGroupA的三個方法都跑一遍,事件結(jié)束。

如果在MyViewGroup的onInterceptTouchEvent()B中返回true,則在MyViewGroupA的onTouchEvent()響應(yīng)前,會把MyViewGroupB的三個方法都跑一遍。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容