Android自定義控件之基本原理(一)
前言:
在日常的Android開發(fā)中會(huì)經(jīng)常和控件打交道,有時(shí)Android提供的控件未必能滿足業(yè)務(wù)的需求,這個(gè)時(shí)候就需要我們實(shí)現(xiàn)自定義一些控件,今天先大致了解一下自定義控件的要求和實(shí)現(xiàn)的基本原理。
自定義控件要求:
1. 應(yīng)當(dāng)遵守Android標(biāo)準(zhǔn)的規(guī)范(命名,可配置,事件處理等)。
2. 在XML布局中科配置控件的屬性。
3. 對(duì)交互應(yīng)當(dāng)有合適的反饋,比如按下,點(diǎn)擊等。
4. 具有兼容性, Android版本很多,應(yīng)該具有廣泛的適用性。
自定義控件學(xué)習(xí)步驟:
1 .View的工作原理
2 .編寫View類
3.為View類增加屬性
4 .繪制屏幕
5. 響應(yīng)用戶消息
6 .自定義回調(diào)函數(shù)
自定義控件兩種方式:
1. 繼承ViewGroup
例如:ViewGroup、LinearLayout、FrameLayout、RelativeLayout等。
2. 繼承View
例如:View、TextView、ImageView、Button等。
自定義控件基本繪制原理:
View的繪制基本上由measure()、layout()、draw()這個(gè)三個(gè)函數(shù)完成
1.)測(cè)量-Measure過(guò)程是計(jì)算視圖大小,View measure過(guò)程相關(guān)方法主要有三個(gè):
public final void measure(int widthMeasureSpec, int heightMeasureSpec) protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
measure調(diào)用onMeasure,onMeasure測(cè)量寬度、高度然后調(diào)用setMeasureDimension保存測(cè)量結(jié)果,measure,setMeasureDimension是final類型,view的子類不需要重寫,onMeasure在view的子類中重寫。
關(guān)于MeasureSpec:
(1)UPSPECIFIED :父容器對(duì)于子容器沒(méi)有任何限制,子容器想要多大就多大.
(2) EXACTLY父容器已經(jīng)為子容器設(shè)置了尺寸,子容器應(yīng)當(dāng)服從這些邊界,不論子容器想要多大的空間.
(3) AT_MOST子容器可以是聲明大小內(nèi)的任意大小.
2.)布局-Layout過(guò)程用于設(shè)置視圖在屏幕中顯示的位置,View layout過(guò)程相關(guān)方法主要要三個(gè):
public void layout(int l, int t, int r, int b) protected boolean setFrame(int left, int top, int right, int bottom) protected void onLayout(boolean changed, int left, int top, int right, int bottom)
layout通過(guò)調(diào)用setFrame(l,t,r,b),l,t,r,b即子視圖在父視圖中的具體位置,onLayout一般只會(huì)在自定義ViewGroup中才會(huì)使用
3.)繪制-draw過(guò)程主要用于利用前兩步得到的參數(shù),將視圖顯示在屏幕上,到這里也就完成了整個(gè)的視圖繪制工作。
public void draw(Canvas canvas) protected void onDraw(Canvas canvas)
通過(guò)調(diào)用draw函數(shù)進(jìn)行視圖繪制,在View類中onDraw函數(shù)是個(gè)空函數(shù),最終的繪制需求需要在自定義的onDraw函數(shù)中進(jìn)行實(shí)現(xiàn),比如ImageView完成圖片的繪制,如果自定義ViewGroup這個(gè)函數(shù)則不需要重載。
自定義控件示例:
這里先介紹繼承View的方式為例,其實(shí)ViewGroup最終的繼承的也是View。這里 模擬一個(gè)需求場(chǎng)景,需要一個(gè)圓形顯示百分比。
public class PercentView extends View { private final static String TAG = PercentView.class.getSimpleName(); private Paint mPaint; public PercentView(Context context) { super(context); } public PercentView(Context context, AttributeSet attrs) { super(context, attrs); } public PercentView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); Log.e(TAG, "onMeasure--widthMode-->" + widthMode); switch (widthMode) { case MeasureSpec.EXACTLY: break; case MeasureSpec.AT_MOST: break; case MeasureSpec.UNSPECIFIED: break; } Log.e(TAG, "onMeasure--widthSize-->" + widthSize); Log.e(TAG, "onMeasure--heightMode-->" + heightMode); Log.e(TAG, "onMeasure--heightSize-->" + heightSize); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); Log.e(TAG, "onLayout"); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(Color.GRAY); // FILL填充, STROKE描邊,FILL_AND_STROKE填充和描邊 mPaint.setStyle(Paint.Style.FILL_AND_STROKE); int with = getWidth(); int height = getHeight(); Log.e(TAG, "onDraw---->" + with + "*" + height); float radius = with / 4; canvas.drawCircle(with / 2, with / 2, radius, mPaint); mPaint.setColor(Color.BLUE); RectF oval = new RectF(with / 2 - radius, with / 2 - radius, with / 2 + radius, with / 2 + radius); //用于定義的圓弧的形狀和大小的界限 canvas.drawArc(oval, 270, 120, true, mPaint); //根據(jù)進(jìn)度畫圓弧 } }
在布局中如何使用
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.whoislcj.views.PercentView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" /> </LinearLayout>
顯示效果:
如果布局文件改成
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.whoislcj.views.PercentView android:layout_width="150dp" android:layout_height="150dp" android:layout_margin="10dp" /> </LinearLayout>
顯示效果變成
總結(jié):
本篇主要介紹Android自定義控件的基本繪制原理,會(huì)在下一篇中介紹如何自定義屬性。希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Android自定義View之組合控件實(shí)現(xiàn)類似電商app頂部欄
- Android自定義控件之開關(guān)按鈕學(xué)習(xí)筆記分享
- Android自定義組合控件之自定義下拉刷新和左滑刪除實(shí)例代碼
- 實(shí)例講解Android應(yīng)用中自定義組合控件的方法
- 在Android開發(fā)中使用自定義組合控件的例子
- Android控件之RatingBar自定義星級(jí)評(píng)分樣式
- Android自定義播放器控件VideoView
- Android中自定義控件的declare-styleable屬性重用方案
- android自定義按鈕示例(重寫imagebutton控件實(shí)現(xiàn)圖片按鈕)
相關(guān)文章
Android學(xué)習(xí)筆記之AndroidManifest.xml文件解析(詳解)
這篇文章主要介紹了Android學(xué)習(xí)筆記之AndroidManifest.xml文件解析,需要的朋友可以參考下2015-10-10android獲取當(dāng)前接入點(diǎn)信息判斷是ctwap還是ctnet實(shí)例代碼
這篇文章主要介紹了android獲取當(dāng)前接入點(diǎn)信息判斷是ctwap還是ctnet的方法,大家參考使用吧2013-11-11Android PopupWindow實(shí)現(xiàn)左側(cè)彈窗效果
這篇文章主要為大家詳細(xì)介紹了Android PopupWindow實(shí)現(xiàn)左側(cè)彈窗效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Android 兩個(gè)ViewPager的聯(lián)動(dòng)效果的實(shí)現(xiàn)
這篇文章主要介紹了Android 兩個(gè)ViewPager的聯(lián)動(dòng)效果的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08Android自定義dialog可選擇展示年月日時(shí)間選擇欄
這篇文章主要介紹了Android自定義dialog可選擇展示年月日時(shí)間選擇欄,非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下2017-03-03Android獲取短信驗(yàn)證碼的實(shí)現(xiàn)方法
為了保護(hù)用戶信息的安全性,開始使用通過(guò)服務(wù)器向用戶發(fā)送驗(yàn)證碼的方式,接下來(lái)通過(guò)本文給大家介紹android獲取短信驗(yàn)證碼的實(shí)現(xiàn)方法,非常不錯(cuò),感興趣的朋友一起看看吧2016-09-09Android基于AdapterViewFlipper實(shí)現(xiàn)的圖片/文字輪播動(dòng)畫控件
這篇文章主要介紹了Android基于AdapterViewFlipper實(shí)現(xiàn)的圖片/文字輪播動(dòng)畫控件,幫助大家更好的理解和學(xué)習(xí)使用Android開發(fā),感興趣的朋友可以了解下2021-04-04Java實(shí)現(xiàn)Andriod帶看括弧的計(jì)算器代碼
這篇文章主要介紹了Java實(shí)現(xiàn)Andriod帶看括弧的計(jì)算器代碼的相關(guān)資料,需要的朋友可以參考下2016-03-03