Android群英傳讀書(shū)筆記(第三章)

上一章

第三章終于進(jìn)入開(kāi)發(fā)的正題了!本章主要介紹自定義控件:

1.控件分為兩類(lèi):ViewViewgroup,通過(guò)ViewGroup整個(gè)界面形成一個(gè)樹(shù)形結(jié)構(gòu),并且ViewGroup負(fù)責(zé)對(duì)子View的測(cè)量與繪制以及傳遞交互事件。

2.Activity包含一個(gè)Window對(duì)象,Window對(duì)象又將一個(gè)DecorView設(shè)置為整個(gè)應(yīng)用的根View。這里所有View的監(jiān)聽(tīng)事件都通過(guò)WindowManagerService來(lái)接收,并通過(guò)Activity對(duì)象來(lái)回調(diào)onClickListener。DecorView在顯示上分為TitleViewContentView兩部分??梢酝ㄟ^(guò)如下代碼獲得ContentView

ViewGroup content=(ViewGroup)findViewById(android.R.id.content);

3.View的測(cè)量在onMeasure中進(jìn)行,系統(tǒng)提供了MeasureSpec類(lèi),是一個(gè)32位的int值,其高2位為測(cè)量模式,低30位為測(cè)量的大小。測(cè)量模式有以下三種:

  • EXACTLY:精確模式,當(dāng)控件指定精確值(例如android:layout_width="50dp")或者指定為match_parent屬性時(shí)系統(tǒng)使用該模式。
  • AT_MOST:最大值模式,指定wrap_content時(shí)系統(tǒng)使用該屬性,View類(lèi)默認(rèn)只支持EXACTLY,如果想使用wrap_content需自己在onMeasure中實(shí)現(xiàn)。
  • UNSPECIFIED:自定義模式,View想多大就多大,通常在繪制自定義View的時(shí)候才使用。

下面是onMeasure的事例代碼:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);// 獲取寬度模式
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);// 獲取寬度值
    int width = 0;
    if (widthMode == MeasureSpec.EXACTLY) {
        width = widthSize;
    } else {
        width = 200;// 自定義的默認(rèn)wrap_content值
        if (widthMode == MeasureSpec.AT_MOST) {
                width = Math.min(widthSize, width);
        }

    }
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);// 獲取高度模式
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);// 獲取高度值
    int height = 0;
    if (heightMode == MeasureSpec.EXACTLY) {
        height = heightSize;
    } else {
        height = 200;// 自定義的默認(rèn)wrap_content值
        if (heightMode == MeasureSpec.AT_MOST) {
            height = Math.min(heightSize, height);
        }
    }
    setMeasuredDimension(width, height);// 最終將測(cè)量的值傳入該方法完成測(cè)量
}

4.View的繪制是通過(guò)onDraw方法實(shí)現(xiàn)的,具體是通過(guò)對(duì)onDraw方法中canvas參數(shù)操作執(zhí)行繪圖。在其他地方,則需要自己創(chuàng)建canvas對(duì)象,創(chuàng)建時(shí)需傳入一個(gè)bitmap對(duì)象, bitmap是用來(lái)保存Canvas.drawXXX繪制的像素信息的,通過(guò)這些繪圖操作改變的實(shí)際上就是bitmap對(duì)象而不是canvas。

5.當(dāng)ViewGroup的大小為wrap_content時(shí),它就會(huì)遍歷所有子View,并調(diào)用其Measure方法獲得其大小,來(lái)決定自身的大小,而在其他模式下則通過(guò)指定值來(lái)設(shè)置自身的大小。然后當(dāng)View測(cè)量完畢以后,ViewGroup會(huì)執(zhí)行它的Layout方法,同樣是遍歷子View并調(diào)用其Layout方法來(lái)確定布局位置。在自定義ViewGroup時(shí),通常會(huì)重寫(xiě)onLayout()方法來(lái)控制子View顯示位置,若需支持wrap_content還需重寫(xiě)onMeasure()方法。ViewGroup通常情況下不需要繪制,但是會(huì)調(diào)用dispatchDraw()方法來(lái)繪制其子View,過(guò)程同樣是遍歷子View。

6.自定義View時(shí)有一些比較重要的回調(diào)方法如下:

onFinishInflate();//從xml加載組件后回調(diào)
onSizeChanged();//組件大小改變時(shí)回調(diào)
onMeasure();//回調(diào)該方法進(jìn)行測(cè)量
onLayout();//回調(diào)該方法來(lái)確定顯示的位置
onTouchEvent();//監(jiān)聽(tīng)到觸摸事件回調(diào)

7.自定義View通常有三種情況:
(1)對(duì)現(xiàn)有控件進(jìn)行拓展:
一般來(lái)說(shuō),會(huì)在onDraw()方法中對(duì)原生控件行為進(jìn)行拓展

@Override
    protected void onDraw(Canvas canvas) {
        //在回調(diào)父類(lèi)方法前,實(shí)現(xiàn)自己的邏輯
        super.onDraw(canvas);
        //在回調(diào)父類(lèi)方法后,實(shí)現(xiàn)自己的邏輯
    }

(2)通過(guò)組合來(lái)實(shí)現(xiàn)新的控件:
這種方式通常需要繼承一個(gè)合適的ViewGroup,再給它添加指定功能的控件,從而組合成新的復(fù)合控件。
(3)重寫(xiě)View來(lái)實(shí)現(xiàn)全新的控件:
當(dāng)Android系統(tǒng)原生的控件無(wú)法滿足我們的需求時(shí),就需要?jiǎng)?chuàng)建一個(gè)全新的自定義View了。通常需要繼承View類(lèi),并重寫(xiě)它的onDraw()、onMeasure()等方法實(shí)現(xiàn)繪制邏輯,同時(shí)通過(guò)重寫(xiě)onTouchEvent()等觸控事件來(lái)實(shí)現(xiàn)交互邏輯,還可以引入自定義屬性,豐富自定義View的可定制性。

8.本章較為淺顯的分析了下事件傳遞的機(jī)制。當(dāng)ViewGroup接收到事件,通過(guò)調(diào)用dispatchTouchEvent(),由這個(gè)方法再調(diào)用onInterceptTouchEvent()方法來(lái)判斷是否要攔截事件,如果返回true則攔截將事件交給onTouchEvent處理,返回false則繼續(xù)向下傳遞。當(dāng)View在接受到事件時(shí),通過(guò)調(diào)用dispatchTouchEvent(),由此方法再調(diào)用onTouchEvent方法,如果返回true則攔截事件自己處理,如果返回false則將事件向上傳遞回ViewGroup并且調(diào)用其onTouchEvent方法繼續(xù)做判斷。

本章中用代碼例舉了很多自定義View,但由于本人對(duì)一些系統(tǒng)繪制的api尚不熟悉,等以后弄懂了再補(bǔ)充

下一章

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

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,836評(píng)論 25 709
  • 第3章 Android 控件架構(gòu)與自定義控件詳解 1.Android控件架構(gòu)控件大致分為兩類(lèi),ViewGroup控...
    cfanr閱讀 416評(píng)論 0 1
  • 子曰:“學(xué)而時(shí)習(xí)之,不亦說(shuō)乎?有朋自遠(yuǎn)方來(lái),不亦樂(lè)乎?人不知而不慍,不亦君子乎?” 有子曰:“其為人也孝弟,而好犯...
    萱萱丫頭閱讀 372評(píng)論 0 0
  • 整幅圖畫(huà)面較大,左疏右密。案主是個(gè)強(qiáng)調(diào)自我存在,對(duì)未來(lái)充滿遐想的人。聯(lián)系案主的實(shí)際情況,對(duì)未來(lái)的迷茫讓他有些躁動(dòng)。...
    喂你些史閱讀 786評(píng)論 1 0
  • 我們從上學(xué)一路過(guò)來(lái)的人都有這樣的困惑,無(wú)論你怎么努力總是比不上有些人不用費(fèi)太大力氣所取得的成績(jī),優(yōu)秀真的大部分是天...
    楓林小筑閱讀 318評(píng)論 2 2

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