在軟件開發過程當中自定義View幾乎必不可少,今天寫下這篇博客記錄本身學習自定義View的第一篇---利用BitmapShader作出圓形圖片的效果java
先上效果圖
android
整個代碼主要使用了三個工具:Paint(畫筆-用來繪圖),BitmapShader(着色器-拉伸圖片,畫筆的助手),Martix(矩陣-用來縮放圖片,着色器的小助手)canvas
總體思路爲:
1.重寫onMeasure方法獲取View寬高的最小值,並將最小值設置爲該View的寬與高
2.獲取圖片資源,並用着色器拉伸放縮圖片
3.將着色器配置給畫筆,並在畫布上將圓形圖案畫出來app
private Paint mPaint; //建立畫筆 private int mRadius; //圖片的半徑大小 private Matrix mMartix; //縮放圖片的矩陣 private Bitmap mBitmap; //Bitmap圖片資源 private BitmapShader mBitmapShader; //Bitmap着色器,對bitmap進行拉伸
//經過獲取圖片的最短寬高讓圖片的寬高保持一致,除以2後即爲半徑大小 mRadius = Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2;
//從新設置視圖的寬高 setMeasuredDimension(mRadius * 2, mRadius * 2);
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mRadius = Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2; setMeasuredDimension(mRadius * 2, mRadius * 2); }
public CircleImageView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); }
if (getDrawable() == null){ return; }
//實例化畫筆 mPaint = new Paint(); //實例化矩陣 mMartix = new Matrix(); //獲取圖片資源,並將drawable圖片轉化爲bitmap圖片,便於咱們後續的畫圖 mBitmap = drawableToBitmap(getDrawable());
if (drawable instanceof BitmapDrawable){ BitmapDrawable bd = (BitmapDrawable) drawable; return bd.getBitmap(); }
//取得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; } }
TileMode有三種:
CLAMP 拉伸
REPEAT 重複
MIRROR 鏡像ide
//實例化着色器 mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//圖片的縮放比例 float mScale = (mRadius * 2.0f) / Math.min(mBitmap.getWidth(), mBitmap.getHeight());
//設置矩陣的偏移度 mMartix.setScale(mScale, mScale);
//設置着色器的矩陣 mBitmapShader.setLocalMatrix(mMartix);
//把着色器配給咱們的畫筆 mPaint.setShader(mBitmapShader);
//調用drawCircle函數用畫布把圓畫出來 canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
@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); }
<com.aefottt.seventhwork.ui.view.CircleImageView android:layout_width="0dp" android:layout_weight="1" android:layout_height="100dp" android:layout_margin="15dp" android:src="@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="@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="@mipmap/aefottt"/>
接下來有時間會在這篇文章後面繼續寫圓角圖片的繪製。函數