前言
在軟體開發程序中自定義View幾乎必不可少,今天寫下這篇博客記錄自己學習自定義View的第一篇---利用BitmapShader做出圓形圖片的效果
先上效果圖

思路
整個代碼主要使用了三個工具:Paint(畫筆-用來繪圖),BitmapShader(著色器-拉伸圖片,畫筆的助手),Martix(矩陣-用來縮放圖片,著色器的小助手)
整體思路為:
1.重寫onMeasure方法獲取View寬高的最小值,并將最小值設定為該View的寬與高
2.獲取圖片資源,并用著色器拉伸放縮圖片
3.將著色器配置給畫筆,并在畫布上將圓形圖案畫出來
代碼實作
首先新建一個CircleImageView.java的類,讓其繼承androidx.appcompat.widget.AppCompatImageView
實作三個構造器方法,我們主要用到含兩個引數的構造方法,
1.定義初始變數
private Paint mPaint; //創建畫筆
private int mRadius; //圖片的半徑大小
private Matrix mMartix; //縮放圖片的矩陣
private Bitmap mBitmap; //Bitmap圖片資源
private BitmapShader mBitmapShader; //Bitmap著色器,對bitmap進行拉伸
2.重寫onMeasure()函式,獲取并設定View的寬高
先通過獲取圖片的最短寬高讓圖片的寬度與高度保持一致,除以2后即為半徑大小
//通過獲取圖片的最短寬高讓圖片的寬高保持一致,除以2后即為半徑大小
mRadius = Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2;
然后再重新設定視圖的寬高
//重新設定視圖的寬高
setMeasuredDimension(mRadius * 2, mRadius * 2);
onMeasure()部分的完整代碼為:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mRadius = Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2;
setMeasuredDimension(mRadius * 2, mRadius * 2);
}
3.進行初始化操作
在第二個構造器中添加init()函式
public CircleImageView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
新建init()函式,在其中進行初始化操作
第一步先判斷是否有圖片資源存在,如果沒有話就不繼續執行后面的方法了
if (getDrawable() == null){
return;
}
接下來我們先對畫筆,矩陣進行初始化設定,并將Drawable轉化為Bitmap
//實體化畫筆
mPaint = new Paint();
//實體化矩陣
mMartix = new Matrix();
//獲取圖片資源,并將drawable圖片轉化為bitmap圖片,便于我們后續的畫圖
mBitmap = drawableToBitmap(getDrawable());
這里需要用到private void drawableToBitmap(Drawable drawable);函式,將Drawable轉化為Bitmap,因為Bitmap一般用來做空白畫布畫圖
在轉換函式中我們先判斷傳進來的drawable是否為BitmapDrawable的實體,如果該drawable為BitmapDrawable的實體,就可以直接進行強制轉換
if (drawable instanceof BitmapDrawable){
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.getBitmap();
}
如果不是的話,就可以通過對應的Bitmap畫布把drawable內容畫到畫布中
//取得drawable的寬和高
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
//建立對應的Bitmap
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
//建立對應bitmap的畫布
Canvas canvas = new Canvas(bitmap);
//把drawable內容畫到畫布中去
drawable.setBounds(0, 0, width, height);
drawable.draw(canvas);
return bitmap;
完整轉換代碼如下:
private Bitmap drawableToBitmap(Drawable drawable){
if (drawable instanceof BitmapDrawable){
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.getBitmap();
}
else {
//取得drawable的寬和高
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
//建立對應的Bitmap
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
//建立對應bitmap的畫布
Canvas canvas = new Canvas(bitmap);
//把drawable內容畫到畫布中去
drawable.setBounds(0, 0, width, height);
drawable.draw(canvas);
return bitmap;
}
}
轉換為Bitmap后,我們回到init()函式,繼續進行對著色器的初始化
新建Bitmap著色器,傳入bitmap物件(避免在onDraw函式中初始化),其中后兩個引數為平鋪模式
TileMode有三種:
CLAMP 拉伸
REPEAT 重復
MIRROR 鏡像
//實體化著色器
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
至此,初始化設定完成,
4.重寫onDraw()函式,進行繪制
在繪制函式中主要設定矩陣mMartix,著色器mBitmapShader和畫筆mPaint三者的屬性
首先我們要為矩陣計算出偏移值,防止因圖片的寬高大于View的寬高而造成拉伸效果,即只在圓圈內顯示一部分的影像,而不能顯示完全
取bitmap寬高的最小值作為基準,計算縮放比例(必須為浮點數) mRadius*2.0f 是指裁剪后View的寬度,在onMeasure()方法里
//圖片的縮放比例
float mScale = (mRadius * 2.0f) / Math.min(mBitmap.getWidth(), mBitmap.getHeight());
然后設定矩陣偏移度
//設定矩陣的偏移度
mMartix.setScale(mScale, mScale);
接著我們讓著色器裝備上設定好的矩陣,這樣就不會出現無法顯示完圖片的問題啦
//設定著色器的矩陣
mBitmapShader.setLocalMatrix(mMartix);
最后,把我們的著色器裝配給畫筆
//把著色器配給我們的畫筆
mPaint.setShader(mBitmapShader);
然后就是整個繪制流程的最后一步啦!呼叫drawCircle函式用畫布把圓畫出來
//呼叫drawCircle函式用畫布把圓畫出來
canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
onDraw()函式整體代碼如下
@Override
protected void onDraw(Canvas canvas) {
//取bitmap寬高的最小值作為基準,計算縮放比例(必須為浮點數) mRadius*2.0f 是指裁剪后View的寬度,在onMeasure()方法里
float mScale = (mRadius * 2.0f) / Math.min(mBitmap.getWidth(), mBitmap.getHeight()); //圖片的縮放比例
//接下來使用矩陣防止因view的寬高大于bitmap的寬高而造成拉伸效果
//設定矩陣的偏移度
mMartix.setScale(mScale, mScale);
//設定著色器的矩陣
mBitmapShader.setLocalMatrix(mMartix);
//把著色器配給我們的畫筆
mPaint.setShader(mBitmapShader);
//呼叫drawCircle函式用畫布把圓畫出來
canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
}
至此函式部分已完全寫完,接下來我們就可以直接去xml檔案里使用我們自定義的View了
<com.aefottt.seventhwork.ui.view.CircleImageView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="100dp"
android:layout_margin="15dp"
android:src="https://www.cnblogs.com/aefottt/archive/2020/12/14/@mipmap/aefottt"/>
<com.aefottt.seventhwork.ui.view.CircleImageView
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="100dp"
android:layout_margin="15dp"
android:src="https://www.cnblogs.com/aefottt/archive/2020/12/14/@mipmap/aefottt"/>
<com.aefottt.seventhwork.ui.view.CircleImageView
android:layout_width="0dp"
android:layout_weight="3"
android:layout_height="150dp"
android:layout_margin="15dp"
android:src="https://www.cnblogs.com/aefottt/archive/2020/12/14/@mipmap/aefottt"/>
圓形圖片的繪制至此結束,然后運行你的app,你會發現有三張圓圓的圖片顯示在你的螢屏上呀,
接下來有時間會在這篇文章后面繼續寫圓角圖片的繪制,
有問題歡迎大家在評論區討論呀
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/234815.html
標籤:其他
下一篇:js-echarts 轉 圖片
