在软件开发过程当中自定义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"/>
接下来有时间会在这篇文章后面继续写圆角图片的绘制。函数