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当中我们会将所有的参数信息设置好,然后交由底层去绘制。


Paint职责
/**
 * 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);
    }
}

运行效果图如下:




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对象,即字体风格,包括粗体,斜体以及衬线体,非衬线体等


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值