Android 详解Canvas与Paint的关系并附有代码实例
前言
Canvas在我们的绘制中扮演的角色其实是会话,我们通常情况下都知道我们能使用Canvas调相关方法去画圆型,矩形图片等,但是最终其实真正的绘制并不是在我们的android层面进行的。当然使用Canvas去画一些东西我们必须要知道四个基本组件如下:
1.一个位图来保存像素
2.Canvas持有绘画的方法drawxx:用画布绘制
3.绘画的模版:(eg. Rect,Path,text,Bitmap)
4.paint:绘画的颜色和样式
Canvas与Paint关系:
1.public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint) { drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter, paint); } 2. public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint) { native_drawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle, useCenter, paint.getNativeInstance()); }3. private static native void native_drawArc(long nativeCanvas, float left, float top, float right, float bottom, float startAngle, float sweep, boolean useCenter, long nativePaint); |
通过上述代码我问发现最后调用到的是底层的一个native_drawArc的本地方法,那么其实本身android的绘制是交由系统底层的so库完成,也就是C的代码。那么在此处我们可以得出一个结论就是,Canvas并不是具体的执行者,而是一个传达着, 在Canvas当中我们会将所有的参数信息设置好,然后交由底层去绘制。
/** * The Paint class holds the style and color information about how to draw * geometries, text and bitmaps. * Paint类保存关于如何绘制的样式和颜色信息 几何图形,文本和位图。 */ public class Paint { private long mNativePaint; private long mNativeShader = 0; |
具体应用实例:
public class ShapesView extends View { private final Paint mNormalPaint; private final Paint mStrokePaint; private final Paint mFillPaint; private final RectF mRect; private final RectF mOval; private final RectF mArc; private final Path mTriangle; private TextPaint mSubTitlePaint; Paint paint; public ShapesView(Context c) { super(c); mRect = new RectF(0.0f, 0.0f, 160.0f, 90.0f); mNormalPaint = new Paint(); mNormalPaint.setAntiAlias(true); mNormalPaint.setColor(0xff0000ff); mNormalPaint.setStrokeWidth(6.0f); mNormalPaint.setStyle(Paint.Style.FILL_AND_STROKE); mStrokePaint = new Paint(); mStrokePaint.setAntiAlias(true); mStrokePaint.setColor(0xff0000ff); mStrokePaint.setStrokeWidth(6.0f); mStrokePaint.setStyle(Paint.Style.STROKE); mFillPaint = new Paint(); mFillPaint.setAntiAlias(true); mFillPaint.setColor(0xff0000ff); mFillPaint.setStyle(Paint.Style.FILL); mOval = new RectF(0.0f, 0.0f, 80.0f, 45.0f); mArc = new RectF(0.0f, 0.0f, 100.0f, 120.0f); mTriangle = new Path(); mTriangle.moveTo(0.0f, 90.0f); mTriangle.lineTo(45.0f, 0.0f); mTriangle.lineTo(90.0f, 90.0f); mTriangle.close(); mSubTitlePaint = new TextPaint(); // 设置paint颜色 mSubTitlePaint.setColor(Color.RED); // 设置字体大小DP mSubTitlePaint.setTextSize(36); // 设置抗锯齿 mSubTitlePaint.setAntiAlias(true); // 设置字体居中 mSubTitlePaint.setTextAlign(Paint.Align.CENTER); mSubTitlePaint.setStrikeThruText(true); paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setColor(Color.BLACK); paint.setAlpha(80); setLayerType(View.LAYER_TYPE_SOFTWARE, null); paint.setShadowLayer(10, 10, 10, Color.BLACK); paint.setTextSize(30); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.translate(50.0f, 50.0f); canvas.drawRoundRect(mRect, 6.0f, 6.0f, mNormalPaint); canvas.translate(0.0f, 110.0f); canvas.drawRoundRect(mRect, 6.0f, 6.0f, mStrokePaint); canvas.translate(0.0f, 110.0f); canvas.drawRoundRect(mRect, 6.0f, 6.0f, mFillPaint); canvas.restore(); canvas.save(); canvas.translate(250.0f, 50.0f); canvas.drawCircle(80.0f, 45.0f, 45.0f, mNormalPaint); canvas.translate(0.0f, 110.0f); canvas.drawCircle(80.0f, 45.0f, 45.0f, mStrokePaint); canvas.translate(0.0f, 110.0f); canvas.drawCircle(80.0f, 45.0f, 45.0f, mFillPaint); canvas.restore(); canvas.save(); canvas.translate(450.0f, 50.0f); canvas.drawOval(mOval, mNormalPaint); canvas.translate(0.0f, 110.0f); canvas.drawOval(mOval, mStrokePaint); canvas.translate(0.0f, 110.0f); canvas.drawOval(mOval, mFillPaint); canvas.restore(); canvas.save(); canvas.translate(625.0f, 50.0f); canvas.drawRect(0.0f, 0.0f, 160.0f, 90.0f, mNormalPaint); canvas.translate(0.0f, 110.0f); canvas.drawRect(0.0f, 0.0f, 160.0f, 90.0f, mStrokePaint); canvas.translate(0.0f, 110.0f); canvas.drawRect(0.0f, 0.0f, 160.0f, 90.0f, mFillPaint); canvas.restore(); canvas.save(); canvas.translate(825.0f, 50.0f); canvas.drawArc(mArc, -30.0f, 70.0f, true, mNormalPaint); canvas.translate(0.0f, 110.0f); canvas.drawArc(mArc, -30.0f, 70.0f, true, mStrokePaint); canvas.translate(0.0f, 110.0f); canvas.drawArc(mArc, -30.0f, 70.0f, true, mFillPaint); canvas.restore(); canvas.save(); canvas.translate(950.0f, 50.0f); canvas.drawArc(mArc, 30.0f, 100.0f, false, mNormalPaint); canvas.translate(0.0f, 110.0f); canvas.drawArc(mArc, 30.0f, 100.0f, false, mStrokePaint); canvas.translate(0.0f, 110.0f); canvas.drawArc(mArc, 30.0f, 100.0f, false, mFillPaint); canvas.restore(); canvas.save(); canvas.translate(50.0f, 400.0f); canvas.drawPath(mTriangle, mNormalPaint); canvas.translate(110.0f, 0.0f); canvas.drawPath(mTriangle, mStrokePaint); canvas.translate(110.0f, 0.0f); canvas.drawPath(mTriangle, mFillPaint); canvas.restore(); canvas.drawText("哈哈哈", 100, 600, mSubTitlePaint); canvas.drawText("画一个很大的圆", 50, 850, paint); //cx和cy为圆点的坐标 int radius = 80; int offest = 40; int startX = radius + offest; int startY = radius + offest + 40; canvas.drawCircle(startX*3, startY*5, radius, paint); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); paint.setShadowLayer(20, -20, 700, Color.BLACK); canvas.drawCircle(startX + radius * 2 + offest, startY, radius, paint); } } |
运行效果图如下:
void setAntiAlias(boolean aa); | 是否抗锯齿 |
void setDither(boolean dither) | 设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰 |
void setLinearText(boolean linearText) | 设置线性文本 |
void setSubpixelText(boolean subpixelText) | 设置该项为true,将有助于文本在LCD屏幕上的显示效果 |
void setUnderlineText(boolean underlineText) | 设置下划线 |
void setStrikeThruText(boolean strikeThruText) | 设置带有删除线的效果 |
void setFakeBoldText(boolean fakeBoldText) | 设置伪粗体文本,设置在小字体上效果会非常差 |
void setFilterBitmap(boolean filter) |
如果该项设置为true,则图像在动画进行中会滤掉对Bitmap图像的优化操作 加快显示速度,本设置项依赖于dither和xfermode的设置 |
void setStyle(Style style) | 设置画笔风格,空心或者实心 FILL,FILL_OR_STROKE,或STROKE Paint.Style.STROKE 表示当前只绘制图形的轮廓,而Paint.Style.FILL表示填充图形。 |
void setColor(int color) | 设置颜色值 |
void setAlpha(int a) | 设置透明图0~255,要在setColor后面设置才生效 |
void setARGB(int a, int r, int g, int b) | 设置RGB及透明度 |
void setStrokeWidth(float width); void setStrokeMiter(float miter); |
当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的粗细度 |
void setStrokeCap(Cap cap) | 当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷末端的图形样式 //如圆形样式Cap.ROUND,或方形样式Cap.SQUARE |
void setStrokeJoin(Join join) | 设置绘制时各图形的结合方式,如平滑效果等 |
Shader setShader(Shader shader) | 设置图像效果,使用Shader可以绘制出各种渐变效果 |
ColorFilter setColorFilter(ColorFilter filter) | 设置颜色过滤器,可以在绘制颜色时实现不用颜色的变换效果 |
Xfermode setXfermode(Xfermode xfermode) | 设置图形重叠时的处理方式,如合并,取交集或并集,经常用来制作橡皮的擦除效果 |
PathEffect setPathEffect(PathEffect effect) | 设置绘制路径的效果,如点画线等 |
MaskFilter setMaskFilter(MaskFilter maskfilter) | 设置MaskFilter,可以用不同的MaskFilter实现滤镜的效果,如滤化,立体等 |
Rasterizer setRasterizer(Rasterizer rasterizer) | 设置光栅化 |
void setShadowLayer(float radius, float dx, float dy, int color) | 在图形下面设置阴影层,产生阴影效果,radius为阴影的角度,dx和dy为阴影在x轴和y轴上的距离,color为阴影的颜色 //注意:在Android4.0以上默认开启硬件加速,有些图形的阴影无法显示。关闭View的硬件加速 view.setLayerType(View.LAYER_TYPE_SOFTWARE, null); |
void setTextAlign(Align align) | 设置文本对齐 |
void setTextSize(float textSize) | 设置字体大小 |
void setTextScaleX(float scaleX) | 设置文本缩放倍数,1.0f为原始 |
void setTextSkewX(float skewX) | 设置斜体文字,skewX为倾斜弧度 |
Typeface setTypeface(Typeface typeface) | 设置Typeface对象,即字体风格,包括粗体,斜体以及衬线体,非衬线体等 |