Android圓形圖片不求人,自定義View實現(BitmapShader使用)
阿新 • • 發佈:2019-02-12
在很多APP當中,圓形的圖片是必不可少的元素,美觀大方。本文將帶領讀者去實現一個圓形圖片自定View,力求只用一個Java類來完成這件事情。
一、先上效果圖
二、實現思路
- 在定義View 的onMeasure()方法裡設定View的寬高相等,應該取寬高中的最小值。
- 在自定義View的onDraw()裡面使用畫筆paint結合BitmapShaper畫出一個圓形區域。
- 上述兩步已經可以實現一個圓形圖片,但是如果圖片大於View的設定的寬高,則只會繪製左上角的局域,內容顯示不完全(如下圖)。因此,還應該做好圖片的縮放。
三、具體實現
1.新建一個java類 CircleImageView繼承 ImageView,這個是完整的程式碼。
public class CircleImageView extends ImageView {
private Paint mPaint; //畫筆
private int mRadius; //圓形圖片的半徑
private float mScale; //圖片的縮放比例
public CircleImageView(Context context) {
super(context);
}
public CircleImageView(Context context, AttributeSet attrs) {
super (context, attrs);
}
public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//因為是圓形圖片,所以應該讓寬高保持一致
int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
mRadius = size / 2;
setMeasuredDimension(size, size);
}
@Override
protected void onDraw(Canvas canvas) {
mPaint = new Paint();
Bitmap bitmap = drawableToBitmap(getDrawable());
//初始化BitmapShader,傳入bitmap物件
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//計算縮放比例
mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());
Matrix matrix = new Matrix();
matrix.setScale(mScale, mScale);
bitmapShader.setLocalMatrix(matrix);
mPaint.setShader(bitmapShader);
//畫圓形,指定好中心點座標、半徑、畫筆
canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
}
//寫一個drawble轉BitMap的方法
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.getBitmap();
}
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
}
}
2. onMeasure()方法裡面,計算好寬高
因為是圓形圖片,所以應該讓寬高保持一致,取測量尺寸寬高中的最小值最為最終結果。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//因為是圓形圖片,所以應該讓寬高保持一致
int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
mRadius = size / 2;
setMeasuredDimension(size, size);
}
3. onDraw()方法裡面畫出圓形圖片,注意看註釋,很詳細。
@Override
protected void onDraw(Canvas canvas) {
mPaint = new Paint();
Bitmap bitmap = drawableToBitmap(getDrawable());
//初始化BitmapShader,傳入bitmap物件
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//計算縮放比例
mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());
Matrix matrix = new Matrix();
matrix.setScale(mScale, mScale);
bitmapShader.setLocalMatrix(matrix);
mPaint.setShader(bitmapShader);
//畫圓形,指定好中心點座標、半徑、畫筆
canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
}
4. 上一步中的將drwable轉換為bitmap的方法。
//寫一個drawble轉BitMap的方法
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.getBitmap();
}
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
}
四、使用該自定義View
1. 佈局檔案裡面使用,此處使用了斯嘉麗的美圖
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.roundimage.MainActivity"
>
<com.roundimage.CircleImageView
android:id="@+id/image1"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:scaleType="centerCrop"
android:src="@drawable/beauty"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/image1"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:text="斯嘉麗·約翰遜"
android:textColor="#333333"
android:textSize="17sp"
/>
</RelativeLayout>
2. 各種效果圖,用於驗證適應性
- 尺寸都指定為200dp
android:layout_width="200dp"
android:layout_height="200dp"
- 尺寸都指定為100dp
android:layout_width="100dp"
android:layout_height="100dp"
- 尺寸都指定不一樣,一個150,一個400
android:layout_width="100dp"
android:layout_height="200dp"
- 尺寸設定為wrap_content
android:layout_width="wrap_content"
android:layout_height="wrap_content"
五、總結
實現圓形圖片有很多種方法:
-
可以使用一些開源框架如Fresco,這個可以參考本人的另一篇部落格 Fresco圖片框架簡介及使用
-
笨辦法,讓視覺給到一張圓形圖片(如果每張圖都需要處理,可能她會打死你)
-
笨辦法,用一個view在上面擋住(這個我寫的自己都笑了)
-
自定義View,就如本文介紹的。
-
自定義Drawble,這個和自定義view可以相互補充。
總之,如果讀者有需要圓形圖的,可以把這個copy一下自己用,就一個類,簡單精巧。
如果覺得本文對你有幫助,請關注、留言、點讚我,謝謝!