1. 程式人生 > >Android 自定義View總結 —— onMeasure()

Android 自定義View總結 —— onMeasure()

說明:本部落格為原創,轉載請註明出處 CSDN-ANDROID筆記棧
由於作者水平有限,錯誤在所難免,請見諒,可以留言,本人會及時改正

索引

onMeasure

該方法為 protected級,只有View的子類 才能過載該方法

// 主要用於測量檢視及其內容的大小,該方法被View類的measure(int,int)方法呼叫
// 過載該方法需要注意幾點:
// 1.必須呼叫setMeasuredDimension(int width, int height)來儲存測量結果,否則會拋IllegalStateException異常
// 2.引數widthSpec,heightSpec並不是大小值,而是由MeasureSpec類生成的“mode&size”複合值
// 3.引數 widthSpec,heightSpec由父類生成 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
// measure方法才是測量的入口,onMeasure中確定測量值
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
...
    onMeasure(int,int);
...
}

onMeasure(int widthMeasureSpec, int heightMeasureSpec)原始碼如下:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // 呼叫setMeasureDemension()確定測量結果
    // getSuggestedMiniumWidth()根據minWidth還有background drawable返回一個最小值
    setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec),
    getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec));
}

View getDefaultSize(int size, int measureSpec)原始碼如下:

public static int getDefaultSize(int size, int measureSpec) {
        int result = size;
        // 通過MeasureSpec類,拆分measureSpec值,獲得mode和size值
        // 後面會對這兩個值做解釋
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        switch (specMode) {
        //無限制模式
        case MeasureSpec.UNSPECIFIED:
            result = size;
            break;
        //至多模式
        case MeasureSpec.AT_MOST:
        //精確模式
        case MeasureSpec.EXACTLY:
            result = specSize;
            break;
        }
        return result;
    }

ViewGroup

ViewGroup 在onMeasure過程中稍有不同,因為你只有知道了所有的子View的大小,才能知道你自己需要多大。
Linearlayout 中遍歷所有子View,如果是橫向佈局則把所有子View的width相加,如果是縱向佈局則把所有子View的height相加(當然還需要考慮Padding,累加的值是不是超過了ParentView允許的值等等)。

// 大致如下
// 具體程式碼可以參考LinearLayout、FrameLayout原始碼
public void onMeasure(int widthMeasureSpec,int heightMeasureSpec){
    int childCount=getChildCount();
    // 遍歷所有子View
    for(int i=0;i<childCount;i++){
        View child=getChildAt(i);
        child.measure(childWidthMeasureSpec,childHeightMeasureSpec);
    }
}

ViewGroup中定義了幾個protected方法用於測量子View

//ViewGroup自己完成所有子View的測量
protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
        final int size = mChildrenCount;
        final View[] children = mChildren;
        for (int i = 0; i < size; ++i) {
            final View child = children[i];
            //過濾GONE狀態的View
            if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
            }
        }
    }
protected void measureChild(View child, int parentWidthMeasureSpec,int parentHeightMeasureSpec) {
        final LayoutParams lp = child.getLayoutParams();

        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                mPaddingLeft + mPaddingRight, lp.width);
        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                mPaddingTop + mPaddingBottom, lp.height);

        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }
protected void measureChildWithMargins(View child,
            int parentWidthMeasureSpec, int widthUsed,
            int parentHeightMeasureSpec, int heightUsed) {
        final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();

        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
                        + widthUsed, lp.width);
        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
                        + heightUsed, lp.height);

        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }
// 生成child measureSpec
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
        int specMode = MeasureSpec.getMode(spec);
        int specSize = MeasureSpec.getSize(spec);

        int size = Math.max(0, specSize - padding);

        int resultSize = 0;
        int resultMode = 0;

        switch (specMode) {
        // Parent has imposed an exact size on us
        case MeasureSpec.EXACTLY:
            if (childDimension >= 0) {
                resultSize = childDimension;
                resultMode = MeasureSpec.EXACTLY;
            } else if (childDimension == LayoutParams.MATCH_PARENT) {
                // Child wants to be our size. So be it.
                resultSize = size;
                resultMode = MeasureSpec.EXACTLY;
            } else if (childDimension == LayoutParams.WRAP_CONTENT) {
                // Child wants to determine its own size. It can't be
                // bigger than us.
                resultSize = size;
                resultMode = MeasureSpec.AT_MOST;
            }
            break;

        // Parent has imposed a maximum size on us
        case MeasureSpec.AT_MOST:
            if (childDimension >= 0) {
                // Child wants a specific size... so be it
                resultSize = childDimension;
                resultMode = MeasureSpec.EXACTLY;
            } else if (childDimension == LayoutParams.MATCH_PARENT) {
                // Child wants to be our size, but our size is not fixed.
                // Constrain child to not be bigger than us.
                resultSize = size;
                resultMode = MeasureSpec.AT_MOST;
            } else if (childDimension == LayoutParams.WRAP_CONTENT) {
                // Child wants to determine its own size. It can't be
                // bigger than us.
                resultSize = size;
                resultMode = MeasureSpec.AT_MOST;
            }
            break;

        // Parent asked to see how big we want to be
        case MeasureSpec.UNSPECIFIED:
            if (childDimension >= 0) {
                // Child wants a specific size... let him have it
                resultSize = childDimension;
                resultMode = MeasureSpec.EXACTLY;
            } else if (childDimension == LayoutParams.MATCH_PARENT) {
                // Child wants to be our size... find out how big it should
                // be
                resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                resultMode = MeasureSpec.UNSPECIFIED;
            } else if (childDimension == LayoutParams.WRAP_CONTENT) {
                // Child wants to determine its own size.... find out how
                // big it should be
                resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                resultMode = MeasureSpec.UNSPECIFIED;
            }
            break;
        }
        //noinspection ResourceType
        return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
    }

MeasureSpec類

MeasureSpec類中定義了三種模式分別是:UNSPECIFIED(無限制模式)、
EXACTLY(精確模式)、AT_MOST(至多模式)

private static final int MODE_SHIFT = 30; //30位

private static final int MODE_MASK  = 0x3 << MODE_SHIFT; //二進位制11(低30位為0),左移了30位

public static final int UNSPECIFIED = 0 << MODE_SHIFT; //二進位制00(低30位為0)

public static final int EXACTLY     = 1 << MODE_SHIFT; //二進位制01(低30位為0)

public static final int AT_MOST     = 2 << MODE_SHIFT; //二進位制11(低30位為0)

UNSPECIFIED模式

ParentView不約束子View,子View想多大就多大

EXACTLY模式

ParentView已經指定一個精確的大小給子View,子View大小已被確定

<TextView android:layout_width="48dp"
          android:layout_height="48dp"/>

AT_MOST模式

ParentView指定一個最大值,子View的大小不能超過這個值

// match_parent 會根據ParentView的模式不同而不同
<TextView android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>

獲取Mode和Size

MeasureSpec類定義了幾個公共靜態方法來獲取Modesize

//java int型別是32位的,MODE_MASK是110...0(共32位),做&操作能取高2位值也就是mode(UNSPECIFIED,EXACTLY,AT_MOST)值
public static int getMode(int measureSpec) {
    return (measureSpec & MODE_MASK);
}
//java int型別是32位的,~MODE_MASK是001...1(共32位),做&操作能取低位30位值也就是size值
public static int getSize(int measureSpec) {
    return (measureSpec & ~MODE_MASK);
}

measureSpec可以通過下面的方法生成

// 低30位size值和高2位mode值
public static int makeMeasureSpec(int size,int mode) {
    if (sUseBrokenMakeMeasureSpec) {
        return size + mode;
    } else {
        return (size & ~MODE_MASK) | (mode & MODE_MASK);
    }
}

Demo

GitHub地址: GitHub
環境: Windows7+JAVA8
IDE: AndroidStdio2.2.2
compileSdkVersion:24
測試裝置:Nexus5(6.0.1)

執行結果截圖
螢幕高度分析

自定義View 過載onMeasure方法並輸出日誌

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);

        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        DLDebug.debug(TAG, "onMeasure: ---->");

        DLDebug.debug(TAG, "[width] " + "mode:" + ViewHelper.parseMeasureMode(widthMode) + " , size:" + widthSize);

        DLDebug.debug(TAG, "[height] " + "mode:" + ViewHelper.parseMeasureMode(heightMode) + " , size:" + heightSize);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        DLDebug.debug(TAG, "[result] " + getMeasuredWidth() + "," + getMeasuredHeight());

        DLDebug.debug(TAG, "<----");
    }
//XML原始碼
<?xml version="1.0" encoding="utf-8"?>
<com.neulion.android.dl.customviewdemo.widget.DLFrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffffff"
        tools:context="com.neulion.android.dl.customviewdemo.MainActivity">

    <com.neulion.android.dl.customviewdemo.widget.DLCustomViewGroup
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ffeb3b">

        <com.neulion.android.dl.customviewdemo.widget.DLCustomView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:background="#ff0000" />

        <com.neulion.android.dl.customviewdemo.widget.DLCustomView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:background="#00ff00" />

        <com.neulion.android.dl.customviewdemo.widget.DLCustomView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:background="#0000ff" />

        <com.neulion.android.dl.customviewdemo.widget.DLCustomView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:background="#000000" />

    </com.neulion.android.dl.customviewdemo.widget.DLCustomViewGroup>

    <com.neulion.android.dl.customviewdemo.widget.DLCustomView
            android:id="@+id/dl_custom_view_exactly"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_gravity="left|center_vertical"
            android:background="@color/colorAccent" />

    <TextView
            android:id="@+id/device_info"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right|top|end"
            android:minHeight="48dp"
            android:maxWidth="240dp"
            android:textSize="14dp"
            android:textColor="#000000"
            tools:ignore="SpUsage" />

</com.neulion.android.dl.customviewdemo.widget.DLFrameLayout>

結果如下:

// onMeasure方法可能會被多次呼叫!
12-08 14:48:03.489  I/DL_DLFrameLayout: onMeasure: ---->
12-08 14:48:03.489  I/DL_DLFrameLayout: [width] mode:EXACTLY , size:1080(1080是當前ParentView及Activity根View允許其子View的最大值,DLFrameLayout寬高設定的是match_parent/wrap_content返回這個結果)
12-08 14:48:03.489  I/DL_DLFrameLayout: [height] mode:EXACTLY , size:1392(這個值可以看出是螢幕的高-statusBar高度-actionBar高度-navigationBar高度的結果)
12-08 14:48:03.489  I/DL_DLCustomViewGroup: onMeasure: ---->
12-08 14:48:03.489  I/DL_DLCustomViewGroup: [width] mode:EXACTLY size:1080
12-08 14:48:03.489  I/DL_DLCustomViewGroup: [height] mode:AT_MOST size:1392
12-08 14:48:03.489  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.489  D/DL_DLCustomView: [width] mode:EXACTLY , size:144 // DLCustomView中寬高設定的是48dp,返回這個結果
12-08 14:48:03.489  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.490  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.490  D/DL_DLCustomView: <----
12-08 14:48:03.490  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.490  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.490  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.490  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.490  D/DL_DLCustomView: <----
12-08 14:48:03.490  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.490  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.490  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.490  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.490  D/DL_DLCustomView: <----
12-08 14:48:03.490  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.490  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.490  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.490  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.490  D/DL_DLCustomView: <----
12-08 14:48:03.490  I/DL_DLCustomViewGroup: [result] 1080,576
12-08 14:48:03.490  I/DL_DLCustomViewGroup: <----
12-08 14:48:03.490  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.490  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.490  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.490  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.490  D/DL_DLCustomView: <----
12-08 14:48:03.508  I/DL_DLFrameLayout: [result] 1080,1392
12-08 14:48:03.508  I/DL_DLFrameLayout: <----
12-08 14:48:03.557  I/DL_DLFrameLayout: onMeasure: ---->
12-08 14:48:03.557  I/DL_DLFrameLayout: [width] mode:EXACTLY , size:1080
12-08 14:48:03.557  I/DL_DLFrameLayout: [height] mode:EXACTLY , size:1536
12-08 14:48:03.557  I/DL_DLCustomViewGroup: onMeasure: ---->
12-08 14:48:03.557  I/DL_DLCustomViewGroup: [width] mode:EXACTLY size:1080
12-08 14:48:03.557  I/DL_DLCustomViewGroup: [height] mode:AT_MOST size:1536
12-08 14:48:03.557  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.557  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.557  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.557  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.557  D/DL_DLCustomView: <----
12-08 14:48:03.557  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.557  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.557  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.557  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.557  D/DL_DLCustomView: <----
12-08 14:48:03.557  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.557  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.557  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.557  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.557  D/DL_DLCustomView: <----
12-08 14:48:03.557  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.557  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.558  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.558  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.558  D/DL_DLCustomView: <----
12-08 14:48:03.558  I/DL_DLCustomViewGroup: [result] 1080,576
12-08 14:48:03.558  I/DL_DLCustomViewGroup: <----
12-08 14:48:03.558  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.558  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.558  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.558  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.558  D/DL_DLCustomView: <----
12-08 14:48:03.558  I/DL_DLFrameLayout: [result] 1080,1536
12-08 14:48:03.558  I/DL_DLFrameLayout: <----
12-08 14:48:03.558  I/DL_DLFrameLayout: onSizeChanged: 1080x1536 , old 0x0
12-08 14:48:03.559  I/DL_DLFrameLayout: onLayout: true [0,0,1080,1536]
12-08 14:48:03.559  I/DL_DLCustomViewGroup: onSizeChanged: 1080x576 , old 0x0
12-08 14:48:03.559  I/DL_DLCustomViewGroup: onLayout: true [0,0,1080,576]
12-08 14:48:03.559  D/DL_DLCustomView: onSizeChanged: 144x144 , old 0x0
12-08 14:48:03.559  D/DL_DLCustomView: onLayout: true [0,0,144,144]
12-08 14:48:03.559  D/DL_DLCustomView: onSizeChanged: 144x144 , old 0x0
12-08 14:48:03.559  D/DL_DLCustomView: onLayout: true [144,144,288,288]
12-08 14:48:03.559  D/DL_DLCustomView: onSizeChanged: 144x144 , old 0x0
12-08 14:48:03.559  D/DL_DLCustomView: onLayout: true [288,288,432,432]
12-08 14:48:03.559  D/DL_DLCustomView: onSizeChanged: 144x144 , old 0x0
12-08 14:48:03.559  D/DL_DLCustomView: onLayout: true [432,432,576,576]
12-08 14:48:03.559  D/DL_DLCustomView: onSizeChanged: 144x144 , old 0x0
12-08 14:48:03.559  D/DL_DLCustomView: onLayout: true [0,696,144,840]
12-08 14:48:03.572  I/DL_DLFrameLayout: onMeasure: ---->
12-08 14:48:03.572  I/DL_DLFrameLayout: [width] mode:EXACTLY , size:1080
12-08 14:48:03.572  I/DL_DLFrameLayout: [height] mode:EXACTLY , size:1536
12-08 14:48:03.572  I/DL_DLCustomViewGroup: onMeasure: ---->
12-08 14:48:03.572  I/DL_DLCustomViewGroup: [width] mode:EXACTLY size:1080
12-08 14:48:03.572  I/DL_DLCustomViewGroup: [height] mode:AT_MOST size:1536
12-08 14:48:03.572  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.572  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.572  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.572  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.572  D/DL_DLCustomView: <----
12-08 14:48:03.572  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.572  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.572  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.572  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.572  D/DL_DLCustomView: <----
12-08 14:48:03.572  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.572  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.572  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.572  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.572  D/DL_DLCustomView: <----
12-08 14:48:03.573  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.573  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.573  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.573  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.573  D/DL_DLCustomView: <----
12-08 14:48:03.573  I/DL_DLCustomViewGroup: [result] 1080,576
12-08 14:48:03.573  I/DL_DLCustomViewGroup: <----
12-08 14:48:03.573  D/DL_DLCustomView: onMeasure: ---->
12-08 14:48:03.573  D/DL_DLCustomView: [width] mode:EXACTLY , size:144
12-08 14:48:03.573  D/DL_DLCustomView: [height] mode:EXACTLY , size:144
12-08 14:48:03.573  D/DL_DLCustomView: [result] 144,144
12-08 14:48:03.573  D/DL_DLCustomView: <----
12-08 14:48:03.574  I/DL_DLFrameLayout: [result] 1080,1536
12-08 14:48:03.574  I/DL_DLFrameLayout: <----
12-08 14:48:03.574  I/DL_DLFrameLayout: onLayout: false [0,0,1080,1536]
12-08 14:48:03.574  I/DL_DLCustomViewGroup: onLayout: false [0,0,1080,576]
12-08 14:48:03.574  D/DL_DLCustomView: onLayout: false [0,0,144,144]
12-08 14:48:03.574  D/DL_DLCustomView: onLayout: false [144,144,288,288]
12-08 14:48:03.574  D/DL_DLCustomView: onLayout: false [288,288,432,432]
12-08 14:48:03.574  D/DL_DLCustomView: onLayout: false [432,432,576,576]
12-08 14:48:03.574  D/DL_DLCustomView: onLayout: false [0,696,144,840]
12-08 14:48:03.575  I/DL_DLFrameLayout: onDraw
12-08 14:48:03.575  I/DL_DLCustomViewGroup: onDraw
12-08 14:48:03.575  D/DL_DLCustomView: onDraw
12-08 14:48:03.575  D/DL_DLCustomView: onDraw
12-08 14:48:03.576  D/DL_DLCustomView: onDraw
12-08 14:48:03.576  D/DL_DLCustomView: onDraw
12-08 14:48:03.576  D/DL_DLCustomView: onDraw