Android自定義控件java
安卓在使用中大多數使用已有的一些控件,用法比較簡單,還有一部分是比較複雜的、用戶本身想的控件,這些就須要進行自定義控件,今天就來簡單說一下自定義控件。android
一、繪製過程canvas
以上就是自定義控件的繪製過程。bash
二、主要內容解釋ide
用於計算視圖的大小,即視圖的寬度和長度。在view中定義爲final類型,要求子類不能修改。measure()函數中又會調用下面的函數:函數
(1)onMeasure(),肯定視圖大小,也就是說measure只是對onMeasure的一個包裝,子類能夠覆寫onMeasure()方法實現本身的計算視圖大小的方式,並經過setMeasuredDimension(width, height)保存計算結果。佈局
(2)關於MeasureSpec:學習
**UPSPECIFIED:**父容器對於子容器沒有任何限制,子容器想要多大就多大.ui
**EXACTLY:**父容器已經爲子容器設置了尺寸,子容器應當服從這些邊界,不論子容器想要多大的空間.spa
**AT_MOST:**子容器能夠是聲明大小內的任意大小.
用於設置視圖在屏幕中顯示的位置。在view中定義爲final類型,要求子類不能修改。layout()函數中有兩個基本操做:
(1)setFrame(l,t,r,b),l,t,r,b即子視圖在父視圖中的具體位置,該函數用於將這些參數保存起來;
(2)onLayout(),在View中這個函數什麼都不會作,提供該函數主要是爲viewGroup類型佈局子視圖用的;
利用前兩部獲得的參數,將視圖顯示在屏幕上,到這裏也就完成了整個的視圖繪製工做。其內部定義了繪圖的基本操做:
(1)繪製背景;
(2)若是要視圖顯示漸變框,這裏會作一些前期工做;
(3)繪製視圖自己,即調用onDraw()函數。在view中onDraw()是個空函數,也就是說具體的視圖都要覆寫該函數來實現本身的顯示。
(4)繪製子視圖,即dispatchDraw()函數。在view中這是個空函數,具體的視圖不須要實現該方法,它是專門爲容器類準備的,也就是容器類必須實現該方法;
(5)應用程序調用了setVerticalFadingEdge或者setHorizontalFadingEdge,若是須要能夠開始繪製漸變框;
(6)繪製滾動條;
從上面能夠看出自定義View須要最少覆寫onMeasure()和onDraw()兩個方法。
三、效果圖展現
四、代碼展現
在java代碼中我加了不少註釋,方便進行理解、學習。
佈局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<sample.sdk.qy.com.androiddemo.Customize
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp"
/>
</LinearLayout>
複製代碼
自定義控件類
public class Customize extends View {
private final static String TAG = Customize.class.getSimpleName();
private Paint mPaint;
private RectF oval;
public Customize(Context context) {
super(context);
init();
}
public Customize(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public Customize(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
mPaint = new Paint();
mPaint.setAntiAlias(true);
oval=new RectF();
}
@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);
switch (widthMode) {
case MeasureSpec.EXACTLY:
break;
case MeasureSpec.AT_MOST:
break;
case MeasureSpec.UNSPECIFIED:
break;
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//設置演顏色
mPaint.setColor(Color.GREEN);
// FILL填充, STROKE描邊,FILL_AND_STROKE填充和描邊
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
//獲取控件的寬度和高度
int with = getWidth();
int height = getHeight();
//設置圓的半徑
float radius = with / 4;
//畫圓,設置顏色
canvas.drawCircle(with / 2, with / 2, radius, mPaint);
mPaint.setColor(Color.BLUE);
//用於定義的圓弧的形狀和大小的界限
oval.set(with / 2 - radius, with / 2 - radius, with / 2
+ radius, with / 2 + radius);
//根據進度畫圓弧
canvas.drawArc(oval, 270, 90, true, mPaint);
//畫出另外一個圓弧
mPaint.setColor(Color.YELLOW);
canvas.drawArc(oval, 360, 120, true, mPaint);
}
}
複製代碼
MainActivity類
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
複製代碼
有興趣的朋友或者有疑問的朋友歡迎留言討論