目录表java
写本篇博客的意图是想总结一下在实际的自定义view开发中,常被咱们所用到的api方法,之因此有了这个想法,是由于自定义view写的多了,总感受掌握的知识点愈来愈杂,毫无章法。因此也就有了这么一个想串串知识点的念头。本文不从概念起笔,也不教你如何实现一个view,把它简单看做一个私人的api文档就好。android
这里贴下画线的api代码:git
drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
这里贴下简单的代码片断:github
/** * @params startX 线段起点的x坐标 * @params startY 线段起点的Y坐标 * @params stopX 线段终点的x坐标 * @params stopY 线段终点y的坐标 */ canvas.drawLine(0,0 , CommentUtils.dip2px(mContext, 150)// px , CommentUtils.dip2px(mContext, 150)// px , linePaint);
这是xml中的布局片断:web
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:background="#787878" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" />
效果图以下
canvas
这里贴下矩形的api方法:api
public RectF (float left, float top, float right, float bottom) public void drawRect (RectF rect, Paint paint)
这里贴下使用的代码片断:svg
/** * RectF: * left 矩形左侧的x坐标 * top 矩形顶部的y坐标 * right 矩形右侧的x坐标 * bottom 矩形底部的y坐标 */ if(rectF == null) rectF = new RectF(0, 0 , CommentUtils.dip2px(mContext, 150)// 单位都是px , CommentUtils.dip2px(mContext, 75)); canvas.drawRect(rectF, rectPaint);
这是xml中的布局片断:布局
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:background="#f0f0f0" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" />
效果图以下:
动画
这里贴下圆形的api方法:
public void drawCircle (float cx, float cy, float radius, Paint paint)
这里贴下使用的代码片断:
/** * float cx 中心点的x坐标 * float cy 中心点的y坐标 * float radius 半径 */ canvas.drawCircle(CommentUtils.dip2px(mContext, 75) , CommentUtils.dip2px(mContext, 75) , CommentUtils.dip2px(mContext, 75) , circlePaint);
这是xml中的布局片断:
<com.mjzuo.views.view.GeometricFigureView android:id="@+id/view_circle" android:layout_width="150dp" android:layout_height="150dp" android:background="#787878" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" />
效果图以下:
默认画出的圆是实心圆,能够经过设置画笔属性来画空心圆,代码以下:
circlePaint = new Paint(); circlePaint.setColor(0xFFCCFFFF); // 充满 // circlePaint.setStyle(Paint.Style.FILL); // 镶边 circlePaint.setStyle(Paint.Style.STROKE);
这是画椭圆的api:
// added in api level 21 // public void drawOval (float left, float top, float right, float bottom, Paint paint) public void drawOval (RectF oval, Paint paint)
方法中RectF便是椭圆的外切矩形。这里贴下椭圆的api方法:
if(mOvalRectF == null) mOvalRectF = new RectF(0, 0 , CommentUtils.dip2px(mContext, 75)// 单位都是px , CommentUtils.dip2px(mContext, 37.5f)); canvas.drawOval(mOvalRectF, mOvalPaint);
这是xml中的布局片断:
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:background="#787878" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" custom:draw_type="3" />
效果图以下:
这里贴下圆角矩形的api方法:
// added in api level 21 //public void drawRoundRect (float left, float top, float right, float bottom, float rx, float ry, Paint paint) public void drawRoundRect (RectF rect, float rx, float ry, Paint paint)
这里贴下圆角矩形的方法:
/** * RectF:矩形区域 * rx:在x轴的半径,焦点在x轴的椭圆长半轴 * ry:在y轴的半径,焦点在x轴的椭圆短半轴 * 能够理解成,在rectF矩形左上角的一个长轴短轴分别为2rx、2ry的标准内切椭圆 */ if(mRoundRectF == null) mRoundRectF = new RectF(0, 0 , CommentUtils.dip2px(mContext, 150)// 单位都是px , CommentUtils.dip2px(mContext, 75)); canvas.drawRoundRect(mRoundRectF , CommentUtils.dip2px(mContext, 36.5f) , CommentUtils.dip2px(mContext, 18.25f) , mRoundRectFPaint);
这是xml中的布局片断:
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:background="#787878" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" custom:draw_type="4" />
效果图以下:
这里贴下弧的api方法:
public void drawArc (RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
这里贴下使用弧的方法:
/** * RectF:矩形边界 * startAngle:开始弧的角度,手表3点钟的方向为0 * sweepAngle:顺时针的扫过的总角度 * useCenter:椭圆的中心是否包含在弧里 */ if(mArcRectF == null) mArcRectF = new RectF(0, 0 , CommentUtils.dip2px(mContext, 150)// 单位都是px , CommentUtils.dip2px(mContext, 75)); canvas.drawArc(mArcRectF , 0 , 90 , true , mArcPaint);
这是xml中的布局片断:
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:background="#787878" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" custom:draw_type="5" />
效果图以下:
咱们主要经过path方法来绘制多边形,固然若是配合画布的旋转、平移等会更加方便,在本demo中是以三角形为例,来演示path的用法,代码片断以下:
/** * 绘制多边形,这里以三角形为例 */ private void drawMoreFigure(Canvas canvas) { // 三角形的起点 if(mMoreFIgurePath == null) mMoreFIgurePath = new Path(); // 三角形的起点 mMoreFIgurePath.moveTo(CommentUtils.dip2px(mContext, 75), 0); // (75,0)->(0,75)画线 mMoreFIgurePath.lineTo(0, CommentUtils.dip2px(mContext, 75)); // (0,75)->(150,75)画线 mMoreFIgurePath.lineTo(CommentUtils.dip2px(mContext, 150) , CommentUtils.dip2px(mContext, 75)); // (150,75)->(75,0)画线,经常使用close替代 // mMoreFIgurePath.lineTo(CommentUtils.dip2px(mContext, 75), 0); // 闭合路径 mMoreFIgurePath.close(); canvas.drawPath(mMoreFIgurePath, mMoreFigurePaint); }
在xml中的代码片断以下:
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:background="#787878" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" custom:draw_type="6" />
效果图以下:
咱们也能够经过画笔Paint来设置是否填充:
mMoreFigurePaint = new Paint(); mMoreFigurePaint.setColor(0xFFCCFFFF); mMoreFigurePaint.setStyle(Paint.Style.STROKE);// 镶边
这里填下填充颜色的api:
// int:16进制。29如下默认模式:PorterDuff.Mode.SRC_OVER,即源像素直接绘制在目标像素上 public void drawColor (int color) // long:将RGB转换成10进制的值 public void drawColor (long color) // 两个参数的重载方法,具体model请查看源码或官网文档 public void drawColor (int color, PorterDuff.Mode mode) // api 29新增方法,相较PorterDuff.Mode新增了一些方法,至关于一个包装类 public void drawColor (int color, BlendMode mode)
填充颜色的方法代码:
canvas.drawColor(0xFFCCFFFF, PorterDuff.Mode.SRC_OVER);
这是xml中的布局片断:
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" custom:draw_type="7" />
效果图以下:
这里是绘制文本的api:
public void drawText (String text, float x, float y, Paint paint)
这是绘制文字的代码:
/** * text:绘制文本 * textX:绘制文本的原点x坐标 * textY:绘制文本基线的y坐标 */ canvas.drawText("我和个人祖国" , CommentUtils.dip2px(mContext, 75) , CommentUtils.dip2px(mContext, 75) , textPaint);
这是xml中的布局片断:
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" custom:draw_type="8" />
效果图以下:
绘制图片位图的api:
public void drawBitmap (Bitmap bitmap, float left, float top, Paint paint)
绘制位图的代码片断:
/** * bitmap * left:绘制的位图的左侧位置 * top:绘制位图的上方位置 */ if(mBitmap == null){ // 将资源图片转换成bitmap,R.mipmap.android:资源图片 mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.icon_android); // 将mBitmap缩放成固定大小 mBitmap = BitmapUtils.conversionBitmap(mBitmap , CommentUtils.dip2px(mContext, 42) , CommentUtils.dip2px(mContext, 42)); } canvas.drawBitmap(mBitmap , 0 , 0 , mBitmapPaint);
这是xml中的布局片断:
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:background="#787878" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" custom:draw_type="9" />
效果图以下:
这是根据path裁剪canvas的代码片断:
private void drawClipPathOnCanval(Canvas canvas) { if(mClipPath == null){ mClipPath = new Path(); // path为圆形矩形。裁剪圆形,弧等都同理 if(mClipRectF == null) mClipRectF = new RectF(0, 0 , CommentUtils.dip2px(mContext, 150)// 单位都是px , CommentUtils.dip2px(mContext, 150)); /** * RectF:矩形轮廓 * rx:圆角矩形的圆角的x半径 * ry:圆角矩形的圆角的y半径 * direction:cw:顺时针、CCW:逆时针 */ mClipPath.addRoundRect(mClipRectF , CommentUtils.dip2px(mContext, 15) , CommentUtils.dip2px(mContext, 15) , Path.Direction.CW); } canvas.clipPath(mClipPath); }
在onDraw方法中进行绘制,本例中是在裁剪后的canvas上绘制了3个矩形,代码片断以下:
// 锁定当前画布 canvas.save(); // 裁剪画布 drawClipPathOnCanval(canvas); // 画红色矩形,矩形方法见上 drawRedRect(canvas); // 画黄色矩形 drawYeRect(canvas); // 画绿色矩形 drawGrRect(canvas); // 恢复画布 canvas.restore();
在xml中的布局片断:
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:background="#787878" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" custom:draw_type="10" />
效果图以下:
这是旋转画布的代码片断:
private void drawRotate(Canvas canvas) { // 画10条线,画线的方法同上 for(int index = 0; index < 9; index ++){ // 画布旋转的角度,每次+10 canvas.rotate(10f); // 由于画布旋转了,因此绘制出来的线段也就跟着旋转了 drawLine(canvas); } }
这是onDraw中的方法,须要在每次旋转前保存下当前的canvas:
// 锁定当前画布 canvas.save(); // 画线 drawRotate(canvas); // 恢复画布 canvas.restore();
这是画线的方法,同上:
private void drawLine(Canvas canvas) { /** * @params startX 线段起点的x坐标 * @params startY 线段起点的Y坐标 * @params stopX 线段终点的x坐标 * @params stopY 线段终点y的坐标 */ canvas.drawLine(0,0 , CommentUtils.dip2px(mContext, 75) , 0 , linePaint); }
这是xml中的布局的代码片断:
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:background="#787878" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" custom:draw_type="11" />
效果如图:
在上面画布旋转代码的基础上,咱们将画布中的线段起点挪动到view的中心点位置,代码片断以下:
private void drawTranslate(Canvas canvas){ /** * dx: 要在x中转换的距离 * dy: 要在y中转换的距离 */ canvas.translate(CommentUtils.dip2px(mContext, 75) , CommentUtils.dip2px(mContext, 75)); }
在onDraw中绘制线段,并平移旋转画布:
// 锁定当前画布 canvas.save(); // 挪动画布 drawTranslate(canvas); // 画线 drawRotate(canvas); // 恢复画布 canvas.restore();
在xml中的代码片断:
<com.mjzuo.views.view.GeometricFigureView android:layout_width="150dp" android:layout_height="150dp" android:background="#787878" android:layout_marginLeft="50dp" android:layout_marginTop="50dp" custom:draw_type="12" />
效果图以下: