日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

android 自定义view控件,Android 自定义View——自定义View控件

發(fā)布時(shí)間:2024/9/27 Android 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 自定义view控件,Android 自定义View——自定义View控件 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Android給我們提供了大量的View控件,但這還是遠(yuǎn)遠(yuǎn)滿足不了我們的要求,有時(shí)候開發(fā)所需要的控件形式是在Android提供的控件中是不存在,這就需要我們自己去定義一個(gè)。那么如何自定義控件?

學(xué)習(xí)自定義控件,首先要先掌握Canvas類的使用。

Canvas

Canvas, 我們稱之為“畫布“,主要適用于繪制View的。

Canvas中提供了大量繪制圖形的方法:

繪制扇形:

drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint):

第一個(gè)參數(shù)RectF對(duì)象,指定扇形的區(qū)域;第二個(gè)參數(shù)是起始角度;第三個(gè)參數(shù)是旋轉(zhuǎn)角度,順時(shí)針旋轉(zhuǎn);第四個(gè)參數(shù)是是否填充,true為填充,false為不填充,也就是為一條弧線;第五個(gè)參數(shù)是繪制圖形的畫筆對(duì)象Paint。

RectF:

通過RectF(float left, float top, float right, float bottom)構(gòu)造器創(chuàng)建RectF對(duì)象,我們通過下圖理解各個(gè)參數(shù)的含義,RectF對(duì)象指代的就是一個(gè)矩形區(qū)域。我們通過這四個(gè)參數(shù)構(gòu)建矩形區(qū)域。

Paint:

是繪制所有圖形所用到的一個(gè)畫筆,我們?cè)谏院笾v解。

drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint)

這個(gè)是將扇形區(qū)域左,上,右,下邊的坐標(biāo)直接輸入,而不是通過RectF對(duì)象。其他參數(shù)同上。

繪制圓形:

drawCircle(float cx, float cy, float radius, Paint paint)

第一、二個(gè)參數(shù)是指圓形的x, y坐標(biāo); 第三個(gè)參數(shù)是半徑; 第四個(gè)參數(shù)是畫筆Paint對(duì)象。

繪制直線:

drawLine(float startX, float startY, float stopX, float stopY, Paint paint)

兩點(diǎn)確定一條直線,第一、二參數(shù)是起始點(diǎn)的坐標(biāo);第三、四參數(shù)是結(jié)束點(diǎn)的坐標(biāo);第五個(gè)參數(shù)畫筆Paint對(duì)象。

drawLines(float[] pts, Paint paint)

多個(gè)點(diǎn)確定一條直線,第一個(gè)參數(shù)是點(diǎn)的數(shù)組;第二個(gè)參數(shù)是畫筆Paint對(duì)象。

drawLines(float[] pts, int offset, int count, Paint paint)

繪制橢圓:

drawOval(float left, float top, float right, float bottom, Paint paint)

前四個(gè)參數(shù)是橢圓的左,上,右,下邊的坐標(biāo),第五個(gè)是畫筆Paint對(duì)象。

drawOval(RectF oval, Paint paint)

第一個(gè)參數(shù)是RectF對(duì)象, 第二個(gè)參數(shù)是畫筆Paint對(duì)象。

繪制矩形:

drawRect(RectF rect, Paint paint)

第一個(gè)參數(shù)是RectF對(duì)象, 第二個(gè)參數(shù)是畫筆Paint對(duì)象。

繪制點(diǎn):

drawPoint(float x, float y, Paint paint)

第一、二個(gè)參數(shù)點(diǎn)的坐標(biāo),第三個(gè)參數(shù)為Paint對(duì)象。

渲染文本:

drawText(String text, float x, floaty, Paint paint)

drawText(CharSequence text, int start, int end, float x, float y, Paint paint)

drawText(char[] text, int index, int count, float x, float y, Paint paint)

drawText(String text, int start, int end, float x, float y, Paint paint)

Canvas中還給我們提供了很多繪制其他圖形的方法,這里我們不在一一列舉。我們來看一下Paint”畫筆“。

Paint

Paint是用于繪制的畫筆,Canvas就像是我們的畫紙,我們需要筆才可以完成一整幅圖。Paint中為我們提供了很多設(shè)置的方法(我們這里只列舉常用的方法):

setARGB(int a, int r, int g, int b)

設(shè)置 Paint對(duì)象顏色,參數(shù)一為alpha透明值

setAlpha(int a)

設(shè)置alpha不透明度,范圍為0~255

setAntiAlias(boolean aa)

是否抗鋸齒,這個(gè)一般是都要設(shè)置的。

setColor(int color)

設(shè)置顏色,這里Android內(nèi)部定義的有Color類包含了一些常見顏色定義

setTextScaleX(float scaleX)

設(shè)置文本縮放倍數(shù),1.0f為原始

setTextSize(float textSize)

設(shè)置字體大小

setUnderlineText(booleanunderlineText)

設(shè)置下劃線

setStrokeCap(Paint.Cap cap)

當(dāng)畫筆樣式為STROKE或FILL_OR_STROKE時(shí),設(shè)置筆刷的圖形樣式,如圓形樣式 Cap.ROUND,或方形樣式Cap.SQUARE

setSrokeJoin(Paint.Join join)

設(shè)置繪制時(shí)各圖形的結(jié)合方式,如平滑效果等

自定義View

現(xiàn)在我們來使用Canvas類自定義一個(gè)View控件。自定義控件步驟如下:

1. 自定義View,首先定義一個(gè)MyView類繼承View類。

2. 重寫View的兩個(gè)構(gòu)造器。

View是包含四個(gè)構(gòu)造器的,我們必須重寫MyWidgetView(Context context, AttributeSet attrs)構(gòu)造器,因?yàn)樵摌?gòu)造器的第二個(gè)參數(shù)是與xml布局文件相聯(lián)系的,如果沒有重寫該構(gòu)造器,將不能在布局中使用該控件。這里我們重寫他的兩個(gè)構(gòu)造器:

public MyView(Context context) {

super(context);

}

public MyView(Context context, AttributeSet attrs) {

super(context, attrs);

}

3. 重寫onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法,定義控件的尺寸:寬度和高度。在布局中使用該控件時(shí)會(huì)會(huì)傳入控件的尺寸,只有當(dāng)傳入尺寸之后且調(diào)用onMesure之后,控件才會(huì)有寬度和高度。

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);

setMeasuredDimension(width, height);//設(shè)置寬和高

}

重寫onDraw(Canvas canvas)方法,我們?cè)谠摲椒ㄖ卸x繪制View,當(dāng)我們?cè)贏ctivity或其他地方使該控件時(shí), UI主線程會(huì)調(diào)用onDraw方法繪制。

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

}

onDraw(Canvas canvas)方法中傳入了一個(gè)Canvas對(duì)象,我們?cè)诙x控件時(shí),使用Canvas繪制。

繪制時(shí)鐘

這里我們通過繪制一個(gè)時(shí)鐘來鞏固一下自定義控件以及Canvas類的使用。

1. 定義一個(gè)MyView繼承View。

2. 重寫MyView(Context context, AttributeSet attrs)構(gòu)造器。

3. 在重寫onMeasureh和onDraw方法。

4. 在onDraw方法中繪制。

大體步驟就是這樣,我們先貼代碼,逐步講解:

public class MyView extends View {

private int width;//設(shè)置高

private int height;//設(shè)置高

private Paint mPaintLine;//定義一個(gè)繪制直線的畫筆

private Paint mPaintSecondLine;//定義一個(gè)繪制直線的畫筆

private Paint mPaintInterCircle;//定義一個(gè)繪制圓的畫筆

private Paint mPaintOutSideCircle;//定義一個(gè)繪制圓的畫筆

private Paint mPaintText;//定義一個(gè)繪制文字的畫筆

private Calendar mCalendar;//創(chuàng)建一個(gè)時(shí)間類

private static final int NEED_INVALIDATE=0X6666;

//操作UI主線程

private Handler handler = new Handler() {

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

switch (msg.what){

case NEED_INVALIDATE:

//跟新時(shí)間

mCalendar=Calendar.getInstance();

invalidate();

sendEmptyMessageDelayed(NEED_INVALIDATE,1000);

break;

}

}

};

public MyView(Context context) {

super(context);

}

public MyView(Context context, AttributeSet attrs) {

super(context, attrs);

//初始化畫直線的畫筆

mPaintLine = new Paint();

mPaintLine.setAntiAlias(true);//消除鋸齒

mPaintLine.setColor(Color.GRAY);//設(shè)置畫筆顏色

mPaintLine.setStyle(Paint.Style.STROKE);//設(shè)置為空心

mPaintLine.setStrokeWidth(10);//設(shè)置寬度

// 初始化秒針的畫筆

mPaintSecondLine = new Paint();

mPaintSecondLine.setAntiAlias(true);//消除鋸齒

mPaintSecondLine.setColor(Color.GRAY);//設(shè)置畫筆顏色

mPaintSecondLine.setStyle(Paint.Style.STROKE);//設(shè)置為空心

mPaintSecondLine.setStrokeWidth(7);//設(shè)置寬度

//初始化內(nèi)圓的畫筆

mPaintInterCircle = new Paint();

mPaintInterCircle.setAntiAlias(true);//消除鋸齒

mPaintInterCircle.setColor(Color.BLACK);

mPaintInterCircle.setStyle(Paint.Style.STROKE);//設(shè)置為空心

mPaintInterCircle.setStrokeWidth(5);

//初始化外圓的畫筆

mPaintOutSideCircle = new Paint();

mPaintOutSideCircle.setAntiAlias(true);//消除鋸齒

mPaintOutSideCircle.setColor(Color.BLACK);

mPaintOutSideCircle.setStyle(Paint.Style.STROKE);//設(shè)置為空心

mPaintOutSideCircle.setStrokeWidth(10);

//繪制文字的畫筆

mPaintText = new Paint();

mPaintText.setAntiAlias(true);//消除鋸齒

mPaintText.setColor(Color.GRAY);

mPaintText.setStyle(Paint.Style.STROKE);//設(shè)置為空心

mPaintText.setTextAlign(Paint.Align.CENTER);

mPaintText.setTextSize(40);

mPaintText.setStrokeWidth(6);

//初始化日歷

mCalendar = Calendar.getInstance();

//發(fā)送一個(gè)消息給UI主線程

handler.sendEmptyMessageDelayed(NEED_INVALIDATE,2000);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);

setMeasuredDimension(width, height);//設(shè)置寬和高

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

// 主線程自動(dòng)調(diào)用

canvas.drawCircle(width / 2, height / 2, 300, mPaintInterCircle);

canvas.drawCircle(width / 2, height / 2, 320, mPaintOutSideCircle);

for(int i=1; i<=12;i++){

canvas.save();//保存當(dāng)前狀態(tài)

canvas.rotate(360 / 12 * i, width / 2, height / 2);

canvas.drawLine(width / 2, height / 2 - 300, width / 2, height / 2 - 270, mPaintLine);

canvas.drawText("" + i, width / 2, height / 2 - 240, mPaintText);

canvas.restore();//回到save()方法保存的狀態(tài)

}

//繪制分針

int minute= mCalendar.get(Calendar.MINUTE);

float minuteDegree = minute/60f*360;

canvas.save();

canvas.rotate(minuteDegree, width / 2, height / 2);

canvas.drawLine(width / 2, height / 2 - 200, width / 2, height / 2 + 40, mPaintLine);

canvas.restore();

//繪制時(shí)針

int hour= mCalendar.get(Calendar.HOUR);

float hourDegree = (hour*60+minute)//(12f*60)*360;

canvas.save();

canvas.rotate(hourDegree, width / 2, height / 2);

canvas.drawLine(width / 2, height / 2 - 170, width / 2, height / 2 + 30, mPaintLine);

canvas.restore();

//繪制秒針

int second = mCalendar.get(Calendar.SECOND);

float secondDegree = second*6;//一秒是6度。

canvas.save();

canvas.rotate(secondDegree, width / 2, height / 2);

canvas.drawLine(width / 2, height / 2 - 220, width / 2, height / 2 + 50, mPaintSecondLine);

canvas.restore();

}

}

繪制兩個(gè)圓形嵌套這個(gè)很簡(jiǎn)單,不用多說。然后繪制刻度,是使用了Canvas畫布的旋轉(zhuǎn),這個(gè)很好理解,我們?cè)诋嫯嫷臅r(shí)候,有時(shí)候要畫一些比較難的角度,我們都是將畫板旋轉(zhuǎn)而不是我們自己換角度。在繪制時(shí)鐘時(shí),我們要繪制時(shí)鐘每個(gè)時(shí)間的刻度,我們可以將要繪制刻度的位置旋轉(zhuǎn)到豎直方向,然后繪制。

for(int i=1; i<=12;i++){

canvas.save();//保存當(dāng)前狀態(tài)

canvas.rotate(360 / 12 * i, width / 2, height / 2);

canvas.drawLine(width / 2, height / 2 - 300, width / 2, height / 2 - 270, mPaintLine);

canvas.drawText("" + i, width / 2, height / 2 - 240, mPaintText);

canvas.restore();//回到save()方法保存的狀態(tài)

}

然后繪制時(shí)針,分針和秒針,他們都是繪制一條線。然后通過獲取當(dāng)前的時(shí)間將這條線指向?qū)Φ脮r(shí)間點(diǎn),也就是偏轉(zhuǎn)對(duì)得角度。這里的偏轉(zhuǎn)我們依然使用畫布的偏轉(zhuǎn)。

以上完成后,我們的時(shí)鐘就差不多完成了,但是,我們發(fā)現(xiàn)我們的表并沒有走。實(shí)現(xiàn)我們繪制的時(shí)鐘轉(zhuǎn)動(dòng)的方式就是然我們的時(shí)鐘每一秒onDraw一次,這樣我們的時(shí)鐘正常了。onDraw是UI主線程不斷調(diào)用重繪界面的,因此我們需要使用到Handler,通過發(fā)送一個(gè)消息給Handler對(duì)象,讓Handler對(duì)象在每一秒重繪一次MyView控件。這里重繪不能調(diào)用onDraw()方法額,而要調(diào)用的是invalidate()方法,invalidate()方法中調(diào)用了onDraw()方法。

//操作UI主線程

private Handler handler = new Handler() {

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

switch (msg.what){

case NEED_INVALIDATE:

//跟新時(shí)間

mCalendar=Calendar.getInstance();

invalidate();

sendEmptyMessageDelayed(NEED_INVALIDATE,1000);

break;

}

}

};

這樣我們的時(shí)鐘也轉(zhuǎn)動(dòng)了……

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的android 自定义view控件,Android 自定义View——自定义View控件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。