目錄表
- android自定義view必備api
- android可拖動圓環刻度條
- android仿滴滴大頭針跳動波紋效果
- android仿網易雲鯨雲音效
寫本篇博客的意圖是想總結一下在實際的自定義view開發中,常被我們所用到的api方法,之所以有了這個想法,是因爲自定義view寫的多了,總感覺掌握的知識點越來越雜,毫無章法。所以也就有了這麼一個想串串知識點的念頭。本文不從概念起筆,也不教你如何實現一個view,把它簡單看作一個私人的api文檔就好。
線段
這裏貼下畫線的api代碼:
drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
這裏貼下簡單的代碼片段:
/**
* @params startX 線段起點的x座標
* @params startY 線段起點的Y座標
* @params stopX 線段終點的x座標
* @params stopY 線段終點y的座標
*/
canvas.drawLine(0,0
, CommentUtils.dip2px(mContext, 150)// px
, CommentUtils.dip2px(mContext, 150)// px
, linePaint);
這是xml中的佈局片段:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#787878"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
/>
效果圖如下
矩形
這裏貼下矩形的api方法:
public RectF (float left,
float top,
float right,
float bottom)
public void drawRect (RectF rect, Paint paint)
這裏貼下使用的代碼片段:
/**
* RectF:
* left 矩形左側的x座標
* top 矩形頂部的y座標
* right 矩形右側的x座標
* bottom 矩形底部的y座標
*/
if(rectF == null)
rectF = new RectF(0, 0
, CommentUtils.dip2px(mContext, 150)// 單位都是px
, CommentUtils.dip2px(mContext, 75));
canvas.drawRect(rectF, rectPaint);
這是xml中的佈局片段:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#f0f0f0"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
/>
效果圖如下:
圓形
這裏貼下圓形的api方法:
public void drawCircle (float cx, float cy, float radius, Paint paint)
這裏貼下使用的代碼片段:
/**
* float cx 中心點的x座標
* float cy 中心點的y座標
* float radius 半徑
*/
canvas.drawCircle(CommentUtils.dip2px(mContext, 75)
, CommentUtils.dip2px(mContext, 75)
, CommentUtils.dip2px(mContext, 75)
, circlePaint);
這是xml中的佈局片段:
<com.mjzuo.views.view.GeometricFigureView
android:id="@+id/view_circle"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#787878"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
/>
效果圖如下:
默認畫出的圓是實心圓,可以通過設置畫筆屬性來畫空心圓,代碼如下:
circlePaint = new Paint();
circlePaint.setColor(0xFFCCFFFF);
// 充滿
// circlePaint.setStyle(Paint.Style.FILL);
// 鑲邊
circlePaint.setStyle(Paint.Style.STROKE);
橢圓
這是畫橢圓的api:
// added in api level 21
// public void drawOval (float left, float top, float right, float bottom, Paint paint)
public void drawOval (RectF oval, Paint paint)
方法中RectF即是橢圓的外切矩形。這裏貼下橢圓的api方法:
if(mOvalRectF == null)
mOvalRectF = new RectF(0, 0
, CommentUtils.dip2px(mContext, 75)// 單位都是px
, CommentUtils.dip2px(mContext, 37.5f));
canvas.drawOval(mOvalRectF, mOvalPaint);
這是xml中的佈局片段:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#787878"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
custom:draw_type="3"
/>
效果圖如下:
圓角矩形
這裏貼下圓角矩形的api方法:
// added in api level 21
//public void drawRoundRect (float left, float top, float right, float bottom, float rx, float ry, Paint paint)
public void drawRoundRect (RectF rect, float rx, float ry, Paint paint)
這裏貼下圓角矩形的方法:
/**
* RectF:矩形區域
* rx:在x軸的半徑,焦點在x軸的橢圓長半軸
* ry:在y軸的半徑,焦點在x軸的橢圓短半軸
* 可以理解成,在rectF矩形左上角的一個長軸短軸分別爲2rx、2ry的標準內切橢圓
*/
if(mRoundRectF == null)
mRoundRectF = new RectF(0, 0
, CommentUtils.dip2px(mContext, 150)// 單位都是px
, CommentUtils.dip2px(mContext, 75));
canvas.drawRoundRect(mRoundRectF
, CommentUtils.dip2px(mContext, 36.5f)
, CommentUtils.dip2px(mContext, 18.25f)
, mRoundRectFPaint);
這是xml中的佈局片段:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#787878"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
custom:draw_type="4"
/>
效果圖如下:
弧
這裏貼下弧的api方法:
public void drawArc (RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
這裏貼下使用弧的方法:
/**
* RectF:矩形邊界
* startAngle:開始弧的角度,手錶3點鐘的方向爲0
* sweepAngle:順時針的掃過的總角度
* useCenter:橢圓的中心是否包含在弧裏
*/
if(mArcRectF == null)
mArcRectF = new RectF(0, 0
, CommentUtils.dip2px(mContext, 150)// 單位都是px
, CommentUtils.dip2px(mContext, 75));
canvas.drawArc(mArcRectF
, 0
, 90
, true
, mArcPaint);
這是xml中的佈局片段:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#787878"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
custom:draw_type="5"
/>
效果圖如下:
多邊形
我們主要通過path方法來繪製多邊形,當然如果配合畫布的旋轉、平移等會更加方便,在本demo中是以三角形爲例,來演示path的用法,代碼片段如下:
/**
* 繪製多邊形,這裏以三角形爲例
*/
private void drawMoreFigure(Canvas canvas) {
// 三角形的起點
if(mMoreFIgurePath == null)
mMoreFIgurePath = new Path();
// 三角形的起點
mMoreFIgurePath.moveTo(CommentUtils.dip2px(mContext, 75), 0);
// (75,0)->(0,75)畫線
mMoreFIgurePath.lineTo(0, CommentUtils.dip2px(mContext, 75));
// (0,75)->(150,75)畫線
mMoreFIgurePath.lineTo(CommentUtils.dip2px(mContext, 150)
, CommentUtils.dip2px(mContext, 75));
// (150,75)->(75,0)畫線,常用close替代
// mMoreFIgurePath.lineTo(CommentUtils.dip2px(mContext, 75), 0);
// 閉合路徑
mMoreFIgurePath.close();
canvas.drawPath(mMoreFIgurePath, mMoreFigurePaint);
}
在xml中的代碼片段如下:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#787878"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
custom:draw_type="6"
/>
效果圖如下:
我們也可以通過畫筆Paint來設置是否填充:
mMoreFigurePaint = new Paint();
mMoreFigurePaint.setColor(0xFFCCFFFF);
mMoreFigurePaint.setStyle(Paint.Style.STROKE);// 鑲邊
填充顏色
這裏填下填充顏色的api:
// int:16進制。29以下默認模式:PorterDuff.Mode.SRC_OVER,即源像素直接繪製在目標像素上
public void drawColor (int color)
// long:將RGB轉換成10進制的值
public void drawColor (long color)
// 兩個參數的重載方法,具體model請查看源碼或官網文檔
public void drawColor (int color, PorterDuff.Mode mode)
// api 29新增方法,相較PorterDuff.Mode新增了一些方法,相當於一個包裝類
public void drawColor (int color, BlendMode mode)
填充顏色的方法代碼:
canvas.drawColor(0xFFCCFFFF, PorterDuff.Mode.SRC_OVER);
這是xml中的佈局片段:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
custom:draw_type="7"
/>
效果圖如下:
文本
這裏是繪製文本的api:
public void drawText (String text,
float x,
float y,
Paint paint)
這是繪製文字的代碼:
/**
* text:繪製文本
* textX:繪製文本的原點x座標
* textY:繪製文本基線的y座標
*/
canvas.drawText("我和我的祖國"
, CommentUtils.dip2px(mContext, 75)
, CommentUtils.dip2px(mContext, 75)
, textPaint);
這是xml中的佈局片段:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
custom:draw_type="8"
/>
效果圖如下:
bitmap
繪製圖片位圖的api:
public void drawBitmap (Bitmap bitmap,
float left,
float top,
Paint paint)
繪製位圖的代碼片段:
/**
* bitmap
* left:繪製的位圖的左側位置
* top:繪製位圖的上方位置
*/
if(mBitmap == null){
// 將資源圖片轉換成bitmap,R.mipmap.android:資源圖片
mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.icon_android);
// 將mBitmap縮放成固定大小
mBitmap = BitmapUtils.conversionBitmap(mBitmap
, CommentUtils.dip2px(mContext, 42)
, CommentUtils.dip2px(mContext, 42));
}
canvas.drawBitmap(mBitmap
, 0
, 0
, mBitmapPaint);
這是xml中的佈局片段:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#787878"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
custom:draw_type="9"
/>
效果圖如下:
畫布裁剪
這是根據path裁剪canvas的代碼片段:
private void drawClipPathOnCanval(Canvas canvas) {
if(mClipPath == null){
mClipPath = new Path();
// path爲圓形矩形。裁剪圓形,弧等都同理
if(mClipRectF == null)
mClipRectF = new RectF(0, 0
, CommentUtils.dip2px(mContext, 150)// 單位都是px
, CommentUtils.dip2px(mContext, 150));
/**
* RectF:矩形輪廓
* rx:圓角矩形的圓角的x半徑
* ry:圓角矩形的圓角的y半徑
* direction:cw:順時針、CCW:逆時針
*/
mClipPath.addRoundRect(mClipRectF
, CommentUtils.dip2px(mContext, 15)
, CommentUtils.dip2px(mContext, 15)
, Path.Direction.CW);
}
canvas.clipPath(mClipPath);
}
在onDraw方法中進行繪製,本例中是在裁剪後的canvas上繪製了3個矩形,代碼片段如下:
// 鎖定當前畫布
canvas.save();
// 裁剪畫布
drawClipPathOnCanval(canvas);
// 畫紅色矩形,矩形方法見上
drawRedRect(canvas);
// 畫黃色矩形
drawYeRect(canvas);
// 畫綠色矩形
drawGrRect(canvas);
// 恢復畫布
canvas.restore();
在xml中的佈局片段:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#787878"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
custom:draw_type="10"
/>
效果圖如下:
畫布旋轉
這是旋轉畫布的代碼片段:
private void drawRotate(Canvas canvas) {
// 畫10條線,畫線的方法同上
for(int index = 0; index < 9; index ++){
// 畫布旋轉的角度,每次+10
canvas.rotate(10f);
// 因爲畫布旋轉了,所以繪製出來的線段也就跟着旋轉了
drawLine(canvas);
}
}
這是onDraw中的方法,需要在每次旋轉前保存下當前的canvas:
// 鎖定當前畫布
canvas.save();
// 畫線
drawRotate(canvas);
// 恢復畫布
canvas.restore();
這是畫線的方法,同上:
private void drawLine(Canvas canvas) {
/**
* @params startX 線段起點的x座標
* @params startY 線段起點的Y座標
* @params stopX 線段終點的x座標
* @params stopY 線段終點y的座標
*/
canvas.drawLine(0,0
, CommentUtils.dip2px(mContext, 75)
, 0
, linePaint);
}
這是xml中的佈局的代碼片段:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#787878"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
custom:draw_type="11"
/>
效果如圖:
畫布平移
在上面畫布旋轉代碼的基礎上,我們將畫布中的線段起點挪動到view的中心點位置,代碼片段如下:
private void drawTranslate(Canvas canvas){
/**
* dx: 要在x中轉換的距離
* dy: 要在y中轉換的距離
*/
canvas.translate(CommentUtils.dip2px(mContext, 75)
, CommentUtils.dip2px(mContext, 75));
}
在onDraw中繪製線段,並平移旋轉畫布:
// 鎖定當前畫布
canvas.save();
// 挪動畫布
drawTranslate(canvas);
// 畫線
drawRotate(canvas);
// 恢復畫布
canvas.restore();
在xml中的代碼片段:
<com.mjzuo.views.view.GeometricFigureView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#787878"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
custom:draw_type="12"
/>
效果圖如下: