Android 自定義View篇(四)自定義屬性詳解

Android 自定義View篇(四)自定義屬性詳解

前言

儘管 Android 系統提供了很多控件,可是有不少酷炫效果仍然是系統原生控件沒法實現的。好在 Android 容許自定義控件,來彌補原生控件的不足。可是在不少初學者看來,自定義 View 彷佛很難掌握。其中有很大一部分緣由是咱們平時看到的自定義 View 使用中,有多種形式,有的寥寥數筆,有的邏輯很複雜,有的直接繼承 View 或 ViewGroup,有的卻直接繼承系統的原生控件,有的能夠直接使用系統定義的屬性,而有的卻自定義了本身的屬性。
實際上實現自定義 View 的方式,從總體上看,只分爲三種:組合控件,繼承控件,自繪控件。而後就是根據須要來添加自定義的屬性,就這麼簡單。android

1、組合控件

組合控件,顧名思義,就是將系統原有的控件進行組合,構成一個新的控件。這種方式下,不須要開發者本身去繪製圖上顯示的內容,也不須要開發者重寫 onMeasure,onLayout,onDraw 方法來實現測量、佈局以及 draw 流程。因此,在實現自定義 view 的三種方式中,這一種相對比較簡單。
實際開發中,標題欄就是一個比較常見的例子。由於在一個 app 的各個界面中,標題欄基本上是大同小異,複用率很高。因此常常會將標題欄單獨作成一個自定義 view,在不一樣的界面直接引入便可,而不用每次都把標題欄佈局一遍。本節就自定義一個標題欄,包含標題和返回按鈕兩個控件,來介紹這種組合控件的實現方式。canvas

一、定義標題欄佈局文件

定義標題欄的佈局文件 custom_title_view.xml,將返回按鈕和標題文本進行組合。這一步用於肯定標題欄的樣子,代碼以下所示:app

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/holo_orange_light">
    <Button
        android:id="@+id/btn_left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dp"
        android:text="Back"
        android:textColor="@android:color/white" />

    <TextView
        android:id="@+id/title_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Title"
        android:textColor="@android:color/white"
        android:textSize="20sp" />
</RelativeLayout>

二、根據給定佈局實現自定義 View

public class CustomTitleView extends FrameLayout implements View.OnClickListener {
    private View.OnClickListener mLeftOnClickListener;
    private Button mBackBtn;
    private TextView mTittleView;

    public CustomTitleView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.custom_title_view, this);
        mBackBtn = findViewById(R.id.btn_left);
        mBackBtn.setOnClickListener(this);
        mTittleView = findViewById(R.id.title_tv);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_left:
                if (mLeftOnClickListener != null) {
                    mLeftOnClickListener.onClick(v);
                }
                break;
        }
    }

    public void setLeftOnClickListener(View.OnClickListener leftOnClickListener) {
        mLeftOnClickListener = leftOnClickListener;
    }

    public void setTittle(String title){
        mTittleView.setText(title);
    }
}

爲了編譯理解和記憶,這裏對該部分作一點說明:ide

  1. 代碼中對外提供了兩個接口,一是動態設置標題,二是使用者能夠自定義返回按鈕的點擊事件。
  2. CustomTitleView 的構造函數,要選擇兩個參數的,選擇其它參數的構造函數會報錯。這一點是筆者開發機測試的結果,暫時不清楚是否是全部手機上都是這樣。
  3. 這裏是繼承的 FrameLayout,可是繼承 LinearLayout,RelativeLayout 等系統佈局控件均可以。之因此要繼承這些系統現成的 ViewGroup,是由於這樣能夠不用再重寫 onMeasure,onLayout 等,這樣省事不少。因爲這裏是一個佈局控件,要用 LayoutInflater 來填充,因此須要繼承 ViewGroup,若是繼承 View 的直接子類,編譯會不經過。因此,CustomTitleView 本身就是一個容器,徹底能夠當成容器使用,此時 CustomTitleView 自身的內容會和其做爲父佈局添加的子控件,效果會疊加,具體的疊加效果是根據繼承的容器特性決定的。

    三、在 Activity 的佈局文件中添加 CustomTitleView

    在 Activity 的佈局文件 activity_custom_view_compose_demo.xml 中,像使用系統控件同樣使用 CustomTitleView 便可。前說了,CustomTitleView 本身就是繼承的現成的系統佈局,因此它們擁有的屬性特性,CustomTitleView 同樣擁有。函數

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.example.demos.customviewdemo.CustomTitleView
        android:id="@+id/customview_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </com.example.demos.customviewdemo.CustomTitleView>
</RelativeLayout>

四、在 Activity 中操做 CustomTitleView

public class CustomViewComposeDemoActivity extends AppCompatActivity {

    private CustomTitleView mCustomTitleView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_custom_view_compose_demo);
        mCustomTitleView = findViewById(R.id.customview_title);
        mCustomTitleView.setTittle("This is Title");
        mCustomTitleView.setLeftOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

    }
}

獲取到 CustomTitleView 實例,設置標題文字,而後自定義"Back"按鈕點擊事件 setLeftOnClickListener()。工具

五、效果圖

按照如上的 4 步,就經過組合控件完成了一個比較簡單的自定義標題欄。可見,這種方式是很是簡單的。
Android 自定義View篇(四)自定義屬性詳解佈局

2、繼承控件

經過繼承系統控件(View 子類控件或 ViewGroup 子類控件)來完成自定義 View,通常是但願在原有系統控件基礎上作一些修飾性的修改,而不會作大幅度的改動,如在 TextView 的文字下方添加下劃線,在 LinearLayout 佈局中加一個蒙板等。這種方式每每都會複用系統控件的 onMeasure 和 onLayout 方法,而只須要重寫 onDraw 方法,在其中繪製一些須要的內容。下面會分別繼承 View 類控件和 ViewGroup 類控件來舉例說明。測試

一、繼承 View 類系統控件

以下示例爲在 TextView 文字下方顯示紅色下劃線,其基本步驟以下:
(1)繼承 View 控件,並重寫 onDraw 方法this

@SuppressLint("AppCompatCustomView")
public class UnderlineTextView extends TextView{
    public UnderlineTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStrokeWidth(5);
        int width = getWidth();
        int height = getBaseline();
        canvas.drawLine(0,height,width,height,paint);
    }
}

(2)在佈局文件中調用
就像使用一個普通 TextView 同樣使用 UnderlineTextView。spa

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.example.demos.customviewdemo.UnderlineTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="50dp"
        android:layout_centerInParent="true"
        android:text="Hello World!"/>
</RelativeLayout>

(3)效果圖
Android 自定義View篇(四)自定義屬性詳解

二、繼承 ViewGroup 類系統控件

以下示例演示,在 layout 佈局上添加一個淺紅色的半透明蒙板,這種需求在工做中也是很是常見的。
(1)繼承 ViewGroup 類系統控件

public class ForegroundLinearLayout extends LinearLayout{
    public ForegroundLinearLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        canvas.drawColor(Color.parseColor("#50FF0000"));
    }
}

(2)在佈局文件中調用
對 ForegroundLinearLayout 的使用,就和使用其父類 LinearLayout 同樣。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
       <com.example.demos.customviewdemo.ForegroundLinearLayout
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:gravity="center">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="Hello World!"
            android:textColor="@android:color/black"
            android:textSize="50dp" />
    </com.example.demos.customviewdemo.ForegroundLinearLayout>
</RelativeLayout>

(3)效果圖
在寬爲全屏寬度,高爲 200dp 的佈局範圍內,繪製完子其子控件 TextView 後,在上面覆蓋了一層淺紅色的半透明蒙板。
Android 自定義View篇(四)自定義屬性詳解
從上面兩個例子可見,繼承系統原有的控件來實現自定義 View,步驟很是簡單,比組合控件簡單多了。可是這一節須要對 Canvas,paint 等繪製方面的知識有必定的瞭解,且還須要對 ViewGroup 的中內容的繪製順序有必定的瞭解,才能在原生控件的基礎上作出想要的效果來。

3、自繪控件

這三種方法中,自繪控件是最複雜的,由於全部的繪製邏輯和流程都須要本身完成。採用自繪控件這種方式時,若是自定義 View 爲最終的葉子控件,那麼須要直接繼承 View;而不過自定義 View 爲容器類控件,則須要直接繼承 ViewGroup。這裏依然針對直接繼承 View 和 ViewGroup 分別舉例進行說明。
一、自繪葉子 View 控件
這裏經過畫一個直方圖來展現自繪 View 控件的實現。

(1)直接繼承 View 類

自繪葉子 View 控件時,最主要工做就是繪製出豐富的內容,這一過程是在重寫的 onDraw 方法中實現的。因爲是葉子 view,它沒有子控件了,因此重寫 onLayout 沒有意義。onMeasure 的方法能夠根據本身的須要來決定是否須要重寫,不少狀況下,不重寫該方法並不影響正常的繪製。

public class HistogramView extends View{

    private Paint mPaint;
    private Path mPath;

    public HistogramView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        mPath = new Path();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //繪製座標軸
        mPaint.reset();
        mPath.reset();
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.STROKE);
        mPath.moveTo(100,100);
        mPath.rLineTo(0,402);
        mPath.rLineTo(800,0);
        canvas.drawPath(mPath,mPaint);
        //繪製文字
        mPaint.reset();
        mPaint.setTextSize(30);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawText("Froyo",160,540,mPaint);
        canvas.drawText("CB",280,540,mPaint);
        canvas.drawText("ICS",380,540,mPaint);
        canvas.drawText("J",480,540,mPaint);
        canvas.drawText("KitKat",560,540,mPaint);
        canvas.drawText("L",690,540,mPaint);
        canvas.drawText("M",790,540,mPaint);
        //繪製直方圖,柱形圖是用較粗的直線來實現的
        mPaint.reset();
        mPaint.setColor(Color.GREEN);
        mPaint.setStrokeWidth(80);
        float[] lines3={
                200,500,200,495,
                300,500,300,480,
                400,500,400,480,
                500,500,500,300,
                600,500,600,200,
                700,500,700,150,
                800,500,800,350,
        };
        canvas.drawLines(lines3,mPaint);
    }
}

(2)在 Activity 界面的佈局文件中引入
和其它自定義控件同樣,直接在佈局文件中引入便可。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.demos.customviewdemo.HistogramView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</RelativeLayout>

(3)效果圖
Android 自定義View篇(四)自定義屬性詳解

二、自繪 ViewGroup 控件

這裏經過自定義一個父佈局控件,並添加一個子 view 來做爲例子講解該方法的實現。
(1)直接繼承 ViewGroup 類
自繪 ViewGroup 控件,須要直接繼承 ViewGroup,在該系列第一篇文章中將繪製流程的時候就講過,onLayout 是 ViewGroup 中的抽象方法,其直接繼承者必須實現該方法。因此這裏,onLayout 方法必需要實現的,若是這裏面的方法體爲空,那該控件的子 view 就沒法顯示了。要想準確測量,onMeasure 方法也是要重寫的。下面例子中,只演示了第一個子 view 的測量和佈局,onLayout 方法中的 child.layout,就完成了對子 view 的佈局。

public class CustomLayout extends ViewGroup {
    public CustomLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (getChildCount() > 0) {
            //只測量第一個child
            View child = getChildAt(0);
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (getChildCount() > 0) {
            //只佈局第一個child
            View child = getChildAt(0);
            child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
        }
    }
}

(2)在佈局文件中和普通父佈局同樣被引入

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.demos.customviewdemo.CustomLayout
        android:layout_width="match_parent"
        android:layout_centerInParent="true"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            android:textSize="50dp"/>

    </com.example.demos.customviewdemo.CustomLayout>

</RelativeLayout>

(3)效果圖
Android 自定義View篇(四)自定義屬性詳解
上述代碼中 android:layout_centerInParent="true"沒有起效,從佈局上看 TextView 應該是處於屏幕的正中央,可是實際結果卻仍是在左上方顯示。這是由於 CustomLayout 控件,並無實現 android:layout_centerInParent 這個屬性,因此是無效的。關於屬性的問題,正是下一節要介紹的內容。

4、在自定義 View 中使用自定義屬性

咱們在使用 Android 原生控件的時候,常常能夠看到在佈局文件中能夠設置不少的屬性值,如:

<TextView
    android:id="@+id/title_tv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="Title"
    android:textColor="@android:color/white"
    android:textSize="20sp" />

這裏能夠根據須要隨時設置 TextView 要顯示的文字,文字顏色,文字大小等各類屬性,給使用者帶來了極大的方便。咱們在使用自定義 View 的時候,也很是但願可以像 TextView 等系統原生控件同樣經過設置屬性值來個性化自定義 View。本節我們在上一節自定義直方圖的基礎上,來介紹自定義屬性的基本使用流程。

一、在 values 中編寫須要的屬性

在 res/values/下新建資源文件,這裏我們命名爲 attrs.xml,在其中編寫所須要的屬性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="HistogramView">
        <attr name="textColor" format="color"/>
        <attr name="histogramColor" format="color"/>
    </declare-styleable>
</resources>

這裏"declare-styleable"中的 name 是自行命名的,能夠理解爲這個自定義屬性集合的名稱。代碼中包含了兩個自定義屬性,名稱分別爲"textColor"和"histogramColor",這裏用來設置直方圖中文字的顏色和直方圖的顏色。format 表示的是屬性的格式,這裏均設置爲"color",表示對應的屬性是用來設置顏色值的。對於"format",後面還會詳細講到。其它的就是固定的格式了,直接套用就行。

二、在自定義 View 中引入屬性

public class HistogramView extends View{

    private Paint mPaint;
    private Path mPath;
    private int mTextColor,mHistogramColor;

    public HistogramView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        mPath = new Path();
        initAttrs(context,attrs);
    }

    private void initAttrs(Context context, AttributeSet attrs){
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HistogramView);
        mTextColor = typedArray.getColor(R.styleable.HistogramView_textColor,Color.BLACK);
        mHistogramColor = typedArray.getColor(R.styleable.HistogramView_histogramColor,Color.GREEN);
        typedArray.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //繪製座標軸
        mPaint.reset();
        mPath.reset();
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.STROKE);
        mPath.moveTo(100,100);
        mPath.rLineTo(0,402);
        mPath.rLineTo(800,0);
        canvas.drawPath(mPath,mPaint);
        //繪製文字
        mPaint.reset();
        mPaint.setTextSize(30);
        mPaint.setColor(mTextColor);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawText("Froyo",160,540,mPaint);
        canvas.drawText("CB",280,540,mPaint);
        canvas.drawText("ICS",380,540,mPaint);
        canvas.drawText("J",480,540,mPaint);
        canvas.drawText("KitKat",560,540,mPaint);
        canvas.drawText("L",690,540,mPaint);
        canvas.drawText("M",790,540,mPaint);
        //繪製直方圖,柱形圖是用較粗的直線來實現的
        mPaint.reset();
        mPaint.setColor(mHistogramColor);
        mPaint.setStrokeWidth(80);
        float[] lines3={
                200,500,200,495,
                300,500,300,480,
                400,500,400,480,
                500,500,500,300,
                600,500,600,200,
                700,500,700,150,
                800,500,800,350,
        };
        canvas.drawLines(lines3,mPaint);
    }
}

將上述代碼和前面第三節中自繪直方圖代碼對比,紅色部分是修改或新增的代碼。初始化屬性的地方,這個過程須要在構造函數中完成。其中,和自定義屬性集創建聯繫,獲取開發者在佈局文件中使用時設置的相應屬性值,若是沒有設置,則會使用默認設置的顏色,分別爲 Color.BLACK 和 Color.GREEN,用完後必定要回收資源。這樣就初始化了文字顏色 mTextColor 值和 mHistogramColor 值,在後面 onDraw 中就使用該值來繪製對應的部分。

三、在佈局文件中設置屬性值

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.demos.customviewdemo.HistogramView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:textColor="@android:color/holo_red_light"
        app:histogramColor="@android:color/holo_blue_bright"/>

</RelativeLayout>

這段代碼中,第 3,10,11 行和以往的佈局文件有些不同,這是使用自定義屬性時的固定格式。第 3 行中,若是佈局文件中沒有這一句,必定要加上,這句是聲明命名空間,只有聲明瞭命名空間才能使用自定義屬性。"app"是該命名空間的名稱,這裏是自行命名的,不必定非要用"app"。第 10 行和 11 行,"app:attrName"表示用的是自定義的屬性,固定用法,前面 mTextColor 和 mHistogramColor 值就是從這裏獲取的。

四、效果圖

Android 自定義View篇(四)自定義屬性詳解

5、自定義屬性格式彙總

在上面一節中,僅僅只是對文字顏色和直方圖顏色的屬性值作了設置,是爲了演示自定義屬性的使用步驟。在實際開發中,徹底能夠定義更多類型的屬性,如顯示文字的內容,文字的大小,直方圖的寬度等。format 也不僅限定於"color",還有"String","Integer"等,多種多樣。本節就彙總一下平時比較經常使用的一些屬性 format。

一、經常使用的 11 種 format 類型

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="SelfAttr">
        <!--1.reference:參考某一資源ID-->
        <attr name="background" format="reference" />
        <!--2. color:顏色值-->
        <attr name = "textColor" format = "color" />
        <!--3.boolean:布爾值-->
        <attr name = "focusable" format = "boolean" />
        <!--4.dimension:尺寸值-->
        <attr name = "layout_width" format = "dimension" />
        <!--5. float:浮點值-->
        <attr name = "fromAlpha" format = "float" />
        <!--6.integer:整型值-->
        <attr name = "lines" format="integer" />
        <!--7.string:字符串-->
        <attr name = "text" format = "string" />
        <!--8.fraction:百分數-->
        <attr name = "pivotX" format = "fraction" />
        <!--9.enum:枚舉值。屬性值只能選擇枚舉值中的一個-->
        <attr name="orientation">
            <enum name="horizontal" value="0" />
            <enum name="vertical" value="1" />
        </attr>
        <!--10.flag:位或運算。屬性值能夠選擇其中多個值-->
        <attr name="gravity">
            <flag name="top" value="0x01" />
            <flag name="bottom" value="0x02" />
            <flag name="left" value="0x04" />
            <flag name="right" value="0x08" />
            <flag name="center_vertical" value="0x16" />
            ...
        </attr>
        <!--11.混合類型:屬性定義時能夠指定多種類型值-->
        <attr name = "background_2" format = "reference|color" />
    </declare-styleable>
</resources>

如上列出了平時工做中在常見的 11 種類型的格式,說是 11 種,但最後一種是前面 10 種的組合而已。看到上述的屬性名稱應該很熟悉吧,都是系統原生控件的屬性名稱。

二、使用舉例

以下對上述屬性的使用一一舉例演示,能夠對照着來理解,都是平時經常使用的系統控件。

<!--1.reference:參考某一資源ID-->
    <ImageView android:background = "@drawable/圖片ID"/>
    <!--2. color:顏色值-->
    <TextView android:textColor = "#00FF00"/>
    <!--3.boolean:布爾值-->
    <Button android:focusable = "true"/>
    <!--4.dimension:尺寸值-->
    <Button android:layout_width = "42dp"/>
    <!--5. float:浮點值-->
    <alpha android:fromAlpha = "1.0"/>
    <!--6.integer:整型值-->
    <TextView android:lines="1"/>
    <!--7.string:字符串-->
    <TextView android:text = "我是文本"/>
    <!--8.fraction:百分數-->
    <rotate android:pivotX = "200%"/>
    <!--9.enum:枚舉值-->
    <LinearLayout
        android:orientation = "vertical">
    </LinearLayout>
    <!--10.flag:位或運算-->
    <TextView android:gravity="bottom|left"/>
    <!--11.混合類型:屬性定義時能夠指定多種類型值-->
    <ImageView android:background = "@drawable/圖片ID" />
    <!--或者-->
    <ImageView android:background = "#00FF00" />

總結

關於自定義 View 的 3 中實現方式以及自定義屬性的使用,這裏就講完了。讀完後,是否是發現基本的實現流程其實很是簡單。固然,本文爲了說明實現流程,因此舉的例子都比較簡單,但不是說繪製內容也同樣簡單。就好像辦理入學手續很簡單,但讀書這件事卻不那麼容易同樣。要完成一些酷炫的自定義 View,還須要好好地掌握 Canvas,Paint,Path 等工具的使用,以及 View 的繪製流程原理。
Android 自定義View篇(四)自定義屬性詳解
Android 自定義View篇(一)View繪製流程
Android 自定義View篇(二)Canvas詳解
Android 自定義View篇(三)Paint詳解
Android 自定義View篇(四)自定義屬性詳解

相關文章
相關標籤/搜索