国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android自定義控件基本原理詳解(一)

2019-12-12 05:50:30
字體:
供稿:網(wǎng)友

前言:

在日常的Android開發(fā)中會經(jīng)常和控件打交道,有時Android提供的控件未必能滿足業(yè)務(wù)的需求,這個時候就需要我們實(shí)現(xiàn)自定義一些控件,今天先大致了解一下自定義控件的要求和實(shí)現(xiàn)的基本原理。

自定義控件要求: 

     1. 應(yīng)當(dāng)遵守Android標(biāo)準(zhǔn)的規(guī)范(命名,可配置,事件處理等)。
     2. 在XML布局中科配置控件的屬性。
     3. 對交互應(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()這個三個函數(shù)完成 
1.)測量-Measure過程是計算視圖大小,View measure過程相關(guān)方法主要有三個: 
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測量寬度、高度然后調(diào)用setMeasureDimension保存測量結(jié)果,measure,setMeasureDimension是final類型,view的子類不需要重寫,onMeasure在view的子類中重寫。 

關(guān)于MeasureSpec: 
(1)UPSPECIFIED :父容器對于子容器沒有任何限制,子容器想要多大就多大. 
(2) EXACTLY父容器已經(jīng)為子容器設(shè)置了尺寸,子容器應(yīng)當(dāng)服從這些邊界,不論子容器想要多大的空間. 
(3) AT_MOST子容器可以是聲明大小內(nèi)的任意大小.

 2.)布局-Layout過程用于設(shè)置視圖在屏幕中顯示的位置,View layout過程相關(guān)方法主要要三個: 
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通過調(diào)用setFrame(l,t,r,b),l,t,r,b即子視圖在父視圖中的具體位置,onLayout一般只會在自定義ViewGroup中才會使用 

3.)繪制-draw過程主要用于利用前兩步得到的參數(shù),將視圖顯示在屏幕上,到這里也就完成了整個的視圖繪制工作。 
public void draw(Canvas canvas)
protected void onDraw(Canvas canvas)
通過調(diào)用draw函數(shù)進(jìn)行視圖繪制,在View類中onDraw函數(shù)是個空函數(shù),最終的繪制需求需要在自定義的onDraw函數(shù)中進(jìn)行實(shí)現(xiàn),比如ImageView完成圖片的繪制,如果自定義ViewGroup這個函數(shù)則不需要重載。 

自定義控件示例:
這里先介紹繼承View的方式為例,其實(shí)ViewGroup最終的繼承的也是View。這里 模擬一個需求場景,需要一個圓形顯示百分比。 

public class PercentView extends View { private final static String TAG = PercentView.class.getSimpleName(); private Paint mPaint; public PercentView(Context context) { super(context); init(); } public PercentView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public PercentView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init(){ mPaint = new Paint(); mPaint.setAntiAlias(true); } @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.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自定義控件的基本繪制原理,會在下一篇中介紹如何自定義屬性,點(diǎn)擊查看

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 竹溪县| 屯留县| 江都市| 海盐县| 色达县| 黄平县| 双柏县| 鸡泽县| 天台县| 龙口市| 阜平县| 措勤县| 达州市| 盱眙县| 日喀则市| 台北市| 会昌县| 南丰县| 陆川县| 济南市| 海安县| 桂平市| 怀集县| 宁河县| 德钦县| 安丘市| 青田县| 花垣县| 武夷山市| 安岳县| 大埔区| 天气| 东宁县| 故城县| 湖南省| 镇沅| 开封县| 石景山区| 白河县| 奉新县| 泰兴市|