画布Canvas绘制基础

QuibblerQuibbler 2020-08-30 约 18 分钟 1908 次阅读

画布Canvas绘制基础

之前提到自定义View中的“神笔”Paint,现在来看看“画布”。Canvas就是自定义View中的“画布”,可以在Canvas上面绘制文本、Bitmap、路径、图形等,绘制设计炫酷的界面。

1、Canvas

关于Canvas更多内容详见Android Developers>Docs>Reference>Canvas。

1.1、Canvas类

Canvas在android.graphics包中,位于源码的../frameworks/base/graphics/java/android/graphics/位置。Canvas类相关的继承关系如下:

RecordingCanvas < DisplayListCanvas < BaseRecordingCanvas < Canvas< BaseCanvas

1.2、Canvas四要素

继续了解Canvas之前,需要先知道Canvas的四个基本组成要素:

①用于容纳像素的位图Bitmap    a Bitmap to hold the pixels

②用于承载绘制调用的Canvas(写入位图)    a Canvas to host the draw calls (writing into the bitmap)

③一个绘制基元(例如Rect,Path,文本,位图)    a drawing primitive (e.g. Rect, Path, text, Bitmap)

④绘制的画笔Paint(颜色和样式)    a paint (to describe the colors and styles for the drawing)

2、获取Canvas

如何获取“画布”Canvas呢?在Android开发中有几个方法,一一道来。

2.1、重写onDraw(Canvas )

自定义View的时候通常重写onDraw(Canvas )方法,传入的唯一参数就是一个Canvas实例。

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

2.2、创建Canvas实例

直接通过构造函数创建Canvas,不过需要传入或者设置绘制用的Bitmap。

//创建Bitmap,Canvas必须。
    Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(bitmap);
    //或者再setBitmap
    Canvas canvas = new Canvas();
    canvas.setBitmap(bitmap);

2.3、借助SurfaceHolder

调用SurfaceHolder的lockCanvas()方法返回Canvas实例,可以在该画布上操作。

Canvas canvas1 = surfaceHolder.lockCanvas();

3、Canvas绘制API

Canvas封装了大量的绘制API,光是draw***()方法就有50余种。大致分为几类,来了解一下,开发项目的时候除了靠经验记住一些,其它的都需要查阅API文档。

3.1、颜色

Canvas提供了一系列的绘制颜色的方法,关于Color详细内容见《Color详解》。

①drawColor(int color)

②drawColor(long color) API level29

③drawColor(int color, PorterDuff.Mode mode)

④drawColor(int color, BlendMode mode)

⑤drawColor(long color,  BlendMode mode)

⑥drawARGB(int a, int r, int g, int b)

⑦drawRGB(int r, int g, int b)

3.2、图形类

Canvas提供了丰富的API绘制各种几何图形。点、线、矩形、圆。

3.2.1、点

①drawPoint(float x, float y,Paint paint) :绘制一个点

②drawPoints(float[] pts,Paint paint):绘制一系列点

③drawPoints(float[] pts, int offset, int count,Paint paint)

3.2.2、线

①drawLine(float startX, float startY, float stopX, float stopY,Paint paint)

②drawLines(@Size(multiple = 4)float[] pts,Paint paint):绘制一系列线条,集合中数量是4整数倍

③drawLines(float[] pts, int offset, int count,Paint paint)

/**
     * 画一系列线。 每行取自pts数组中的4个连续值. 
     * 因此,要绘制1条线,数组必须至少包含4个值。
     *
     * @param pts 要绘制的点数组[x0 y0 x1 y1 x2 y2 ...]
     * @param offset 绘制前要跳过的数组中的值数。
     * @param count 跳过数组中offset个值后,要继续处理的数组中的值数。由于每行使用4个值,至少为4的整数倍。
     * @param paint 用于画点的Paint
     */
    public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count, @NonNull Paint paint) {
        super.drawLines(pts, offset, count, paint);
    }

3.2.3、椭圆/圆

①drawOval(RectF oval,Paint paint):绘制椭圆,RectF矩形的内切椭圆

②drawOval(float left, float top, float right, float bottom,Paint paint)

③drawCircle(float cx, float cy, float radius,Paint paint):绘制圆形

3.2.4、扇形

①drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)

/**
     * 绘制指定的圆弧,将其缩放以适合指定的椭圆形.
     * 如果起始角度为负或> = 360,则将起始角度视为以360为模的起始角度。
     * @param oval 椭圆的边界,用于定义圆弧的形状和大小
     * @param startAngle 弧开始的起始角度(度)
     * @param sweepAngle 顺时针测量的扫描角度(度)
     * @param useCenter 如果为true,则将椭圆的中心包括在圆弧中,并在对其进行描边时将其关闭。 这会画一个楔子
     * @param paint 用于画弧的Paint
     */
    public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
            @NonNull Paint paint) {
        super.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
    }

3.2.5、矩形

①drawRect(float left, float top, float right, float bottom,Paint paint)

②drawRect(Rect r,Paint paint):借助Rect绘制矩形

③drawRect(RectF rect, Paint paint):使用RectF绘制

④drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,Paint paint):绘制圆角矩形,最后两个参数rx、ry是围绕角落的椭圆的X、Y半径

⑤drawRoundRect(RectF rect, float rx, float ry,Paint paint)

⑥drawDoubleRoundRect(RectF outer,float[] outerRadii,RectF inner,float[] innerRadii,Paint paint):绘制内外两个矩形,数组大小8(上下左右四个角xy各两个值)

⑦drawDoubleRoundRect(RectF outer, float outerRx, float outerRy,RectF inner, float innerRx, float innerRy,Paint paint)

3.3、文字

绘制文本时,设置绘制文字的大小通过Paint的setTextSize(float textSize)方法,同时注意一般给Paint设置Style为Paint.Style.FILL_AND_STROKE,不然绘制出的文字是镂空的,当然以实际需要为准。

①drawText(String text, float x, float y,Paint paint):在Canvas中的坐标(x,y)开始绘制文本text

②drawText(String text, int start, int end, float x, float y,Paint paint):绘制text中从start(含)开始,到第end(不含)字符

③drawText(char[] text, int index, int count, float x, float y,Paint paint)

④drawText(String text, int start, int end, float x, float y,Paint paint)

⑤drawTextOnPath(String text,Path path, float hOffset,float vOffset,Paint paint):在指定的Path路径上绘制文字,比较实用的一个方法,绘制有趣的文字。

⑥drawTextOnPath(char[] text, int index, int count,Path path,float hOffset, float vOffset,Paint paint)

/**
     * 根据路径去绘制文本
     *
     * @param text String 绘制的文本内容
     * @param path 路径
     * @param hOffset float 距离路径开始位置的偏移量
     * @param vOffset float 距离路径上下的偏移量(可以为负数)
     * @param paint 画笔对象
     */
    public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
            float vOffset, @NonNull Paint paint) {
        super.drawTextOnPath(text, path, hOffset, vOffset, paint);
    }

⑦drawTextRun(char[] text, int index, int count, int contextIndex,int contextCount, float x, float y, boolean isRtl,Paint paint):高级操作,主要针对阿拉伯语RTL,详见扔物线大神HenCoder Android开发进阶:自定义 View 1-3 drawText() 文字的绘制

⑧drawTextRun(CharSequence text, int start, int end, int contextStart,int contextEnd, float x, float y, boolean isRtl,Paint paint)

⑨drawTextRun(MeasuredText text, int start, int end, int contextStart,int contextEnd, float x, float y, boolean isRtl,Paint paint)

        ⑩drawPosText(char[] text, int index, int count,@Size(multiple = 2) float[] pos,Paint paint):不适合复杂Text的绘制,而且不适合表情符号,所以被废弃

        ⑪drawPosText(String text,@Size(multiple = 2) float[] pos,Paint paint)

3.4、图像

①drawBitmap(Bitmap bitmap, float left, float top,Paint paint)

②drawBitmap(Bitmap bitmap,Rect src,RectF dst,Paint paint)

③drawBitmap(Bitmap bitmap,Rect src,Rect dst,Paint paint)

④drawBitmap(Bitmap bitmap,Matrix matrix,Paint paint)

3.5、Path路径

①drawPath(@NonNull Path path, @NonNull Paint paint):绘制复杂路径,关于Path以后再详细了解。

/**
     * 使用指定的涂料绘制指定的路径。 路径将根据绘画中的样式填充或构图。
     *
     * @param path 绘制的路径
     * @param paint 用于绘制路径的Paint
     */
    public void drawPath(@NonNull Path path, @NonNull Paint paint) {
        super.drawPath(path, paint);
    }

相关资料:

        Android Developers > Docs > Reference > Canvas

        Canvas and Drawables

        Android canvas常用的方法解析

        Android Canvas方法总结

        Android Canvas总结

        Android中的canvas介绍

        Android Canvas基础详解

        Android Canvas进阶常用API

        HenCoder Android开发进阶:自定义 View 1-3 drawText() 文字的绘制

Canvas DrawText详解

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w