上篇文章介绍了自定义View的创建流程,从宏观上给出了一个自定义View的创建步骤,本篇是上一篇文章的延续,介绍了自定义View中两个必不可少的工具Canvas和Paint,从细节上更进一步的讲解自定义View的详细绘制方法。如果把自定义View比作盖一座房子,那么上篇文章就相当于教会了我们怎么一步步的搭建房子的骨架,而本篇文章将要教会我们的是为房子的骨架添砖加瓦直至成型,甚至是怎么装修。
Canvas为了后文更为方便的讲解Canvas的常用方法的使用,我们先来做一些准备工作,创建一个自定义View框架,先初始化一下Paint画笔,并设置相关方法:
public class StudyView extends View { private Paint mPaint; private Context mContext; public StudyView(Context context) { super(context); init(context); } public StudyView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context) { mContext = context; mPaint = new Paint(); mPaint.setAntiAlias(true); // 消除锯齿 mPaint.setStrokeWidth(5); // 设置笔尖宽度 mPaint.setStyle(Paint.Style.STROKE); // 不填充 } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } } 绘制圆弧和扇形Canvas提供drawArc()方法,通过传递不同的参数可用来绘制圆弧和扇形,此方法有两个重载方法,详细参数如下:
drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
left:扇形或圆弧所占区域的左边界线x坐标
top:扇形或圆弧所占区域的上边界线y坐标
right:右边界线x坐标
bottom:下边界线y坐标
startAngle:扇形或圆弧的起始角度
sweepAngle:扫过的角度
userCenter:此参数可以理解为true就是画扇形,false就是画圆弧
paint:画笔
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
此方法第一个参数是一个RectF类,也是边界,就是把一个方法的left,top,right,bottom封装到了RectF类中,剩余参数与上一个方法一致。
接下来用着两个重载方法分别绘制两个90°的扇形和两个90°的圆弧:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 绘制扇形 canvas.drawArc(0, 0, 200, 200, 0, 90, true, mPaint); RectF rectF = new RectF(0, 0, 200, 200); canvas.drawArc(rectF, 180, 90, true, mPaint); // 绘制圆弧 canvas.drawArc(300, 0, 500, 200, 0, 90, false, mPaint); RectF rectF1 = new RectF(300, 0, 500, 200); canvas.drawArc(rectF1, 180, 90, false, mPaint); }绘制效果如下图所示,另外需要说明的一点是,drawArc的第五个参数startAngle中的角度,0°是指坐标系中第四象限中与x重合的角度,顺时针方向代表角度增大的方向,如下图中红色线条所示。
绘制Bitmap在Canvas中提供了drawBitmap方法,此方法可以让我们直接获取一张图片绘制到画布上,有了它可以让我们的自定义View锦上添花,同时也让我们实现一些复杂效果有了一个更加方便的途径。下面是drawBitmap的几个比较常用的重载方法:
drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
bitmap:Bitmap资源文件
left和top:代表了图片左上角落入的位置坐标。
top:看2
paint:画笔
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
src:在Bitmap图片上截取一部分作为绘制源,可null
det:将绘制目标拉伸平铺到det指定的矩形中
drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
同第二个重载方法,几乎一毛一样。
drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)
matrix:Matrix的参数传入是的drawBitmap功能变得异常强大,让此方法有意思了许多,通过matrix可以实现图片的平移(postTranslate())、缩放(postScale())、旋转(postRotate())、错切(postSkew())等等花式炫酷效果,由于Matrix的用法稍微多一些,篇幅限制,这里就先一带而过了,感兴趣的朋友可以自行探索。
在onDraw方法中drawBitmap的以上重载方法,注意在使用完Bitmap之后记得用Bitmap.recycle()来回收掉资源,以防止oom。
/** drawBitmap */ Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), android.R.mipmap.sym_def_app_icon); // 绘制图片 canvas.drawBitmap(bitmap, 0, 300, null); // 将图片拉伸平铺在RectF矩形内 canvas.drawBitmap(bitmap, null, new RectF(200, 300, 500, 500), null); // 截取图片的四分之一拉伸平铺在RectF矩形内 canvas.drawBitmap(bitmap, new Rect(0, 0, bitmap.getWidth()/2, bitmap.getHeight()/2), new RectF(500, 300, 800, 500), null); Matrix matrix = new Matrix(); matrix.postTranslate(800, 300); // 将bitmap平移到此位置 canvas.drawBitmap(bitmap, matrix, mPaint); // 为防止oom,及时回收bitmap bitmap.recycle();效果如下图(红框内)。