【朝花夕拾】Android自定义View篇之(二)Canvas常用功能

2023-10-21 01:50

本文主要是介绍【朝花夕拾】Android自定义View篇之(二)Canvas常用功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

       转在请申明,转自【https://www.cnblogs.com/andy-songwei/p/10960012.html】,谢谢!

       上一篇讲View的绘制流程中讲到过,最后一步是draw流程,在这个过程中,子view需要重写onDraw方法来画出自己的内容。在自定义View绘制自身内容的时候,系统提供了3个非常重要的类来帮助开发者画各种炫酷的图形:Canvas、Paint、Path。本篇主要介绍Canvas相关的内容,Paint和Path在后面会单独再做介绍。官方文档中介绍的Canvas相关的API很多,本文主要介绍和梳理一些比较常用的实用功能。

       本文的主要内容如下:

 

 

一、一切的开始——onDraw

        如下代码展示了一个自定义view画图形的一个非常简单的示例。这里onDraw方法的参数Canvas就是本篇的主角了,中文意思“画布”,意思就是所有“画”的内容都是在这张画布上完成的。

1 Paint paint = new Paint();
2 @Override
3 protected void onDraw(Canvas canvas) {
4 super.onDraw(canvas);
5 // 绘制一个原点坐标(300,300),半径为200的圆
6 canvas.drawCircle(300, 300, 200, paint);
7 }

     代码非常简单,可见自定义绘制上手非常容易。

 

二、Canvas基本的draw功能

       Canvas包含了一些画基本图案的函数,基本都是以drawXXX的形式给出的。

  1、坐标系

       这里先简单介绍一下画图中所参照的坐标系,是以当前View位置的左上角为原点(0,0),水平方向向右为X轴正方向,竖直向下为Y轴正方向,这里的View位置是个相对值,它取决于开发者把它放在哪里。坐标系大致如下所示,注意和平时我们数学上坐标系略有差别。

 

  2、Paint

       在Canvas的这些drawXXX方法中会用到paint类,它是画笔,会决定绘制出来的图形的颜色,是填充整个图形还是仅绘制边框线条等多个属性。这些会在以后专门介绍Paint的时候再讲,这里先提醒读者注意,在笔者截取的效果图中,咱们这里先只关注形状,关于piant,一律先用默认的填充。

  3、drawColor()颜色填充

    (1)函数原型:drawColor(@color int color)。

    (2)作用:将整个绘制区域填充为指定颜色(可以设置透明度)。

    (3)示例:一般有三种方式来引用颜色值

1  //使用系统提供的颜色
2  canvas.drawColor(Color.BLACK);
3  //使用自定义颜色
4  canvas.drawColor(Color.parseColor("#000000"));
5  //使用color.xml中定义的颜色值
6  canvas.drawColor(getResources().getColor(R.color.black));

    (4)效果:

    (5)其它设置颜色的方法

          1)drawRGB(int r, int g, int b):根据RGB值来设置颜色

          2)drawARGB(int a, int r, int g, int b):根据透明度和RGB的值来设置颜色。

      上述中的几种方法,适用于在绘制前设置底色,或者在绘制完成后添加一层半透明蒙板。

  4、drawCircle画圆

    (1)函数原型drawCircle(float centerX, float centerY, float radius, Paint paint)。参数依次为:X坐标,Y坐标,半径,画笔。

    (2)作用:以原点(centerX,centerY),半径radius,画一个圆。

    (3)示例:

1  // 绘制一个原点坐标(300,300),半径为200的圆
2  canvas.drawCircle(300, 300, 200, paint);

    (4)效果

      

  5、drawRect画矩形

    (1)函数原型:drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) 参数分别为左边、顶部、右边、底部四条边的坐标值。

    (2)根据给定的4条边框的坐标,来画矩形。

    (3)示例:

1 canvas.drawRect(100, 100, 500, 500, paint);

    (4)效果

     (5)其他函数

          1) drawRect(@NonNull Rect r, @NonNull Paint paint)。实际上就是将前面函数定义为一个Rect来作为参数,作用和上面一样。

          2)示例,效果和上述一样。

1 canvas.drawRect(new Rect(100,100,500,500),mPaint);

 

  6、drawPoint画点

    (1)函数原型:drawPoint(float x, float y, @NonNull Paint paint)。参数x,y分别为该点的坐标,点的大小和形状由paint决定。

    (2)功能:在指定x,y坐标处画点

    (3)示例

1 canvas.drawPoint(50, 50, paint);

    (4)效果(和画圆很类似,其实也可以用来画圆)

    (5)画多个点

          1)drawPoints(float[] pts, int offset, int count,@NonNull Paint paint)。pts 这个数组是点的坐标,每两个成一对; offset 表示跳过数组的前几个数再开始记坐标; count 表示一共有多个数参与绘制。

          2)示例:

1  float[] points = {0, 0, 50, 50, 50, 100, 100, 50, 100, 100, 150, 50};
2  canvas.drawPoints(points, 2 /* 跳过两个数,即前两个 0 */,
3  8 /* 一共绘制 8 个数(4 个点)*/, paint);

          3)效果。效果图中4个点的坐标分别为(50,50)、(50,100)、(100,50)、(100,100)

          4)drawPoints( @NonNull float[] pts, @NonNull Paint paint);就是默认将上述函数的offset设置为0,count设置为所有数据参与绘制。

 

  7、drawOval画椭圆

    (1)函数原型:drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)。参数分别为四个顶点所在切线坐标。

    (2)作用:4个参数确定了一个矩形的4条边框,这个矩形确定了一个椭圆。该函数用于画出这个指定的椭圆。

    (3)示例

1 canvas.drawOval(50, 50, 350, 200, paint);

    (4)效果

    (5)其它构造函数 : drawOval(RectF rect, Paint paint)

 

  8、drawLine画直线

    (1)函数原型:drawLine(float startX, float startY, float stopX, float stopY, Paint paint)。参数值分别为起始点坐标和结束点坐标。

    (2)作用:根据给定的起始点和结束点画直线

    (3)示例

1 canvas.drawLine(200, 200, 800, 500, paint);

    (4)效果

    (5) 批量画线:drawLines(float[] pts, int offset, int count,Paint paint) / drawLines(float[] pts, Paint paint)。使用方法参照批量画圆。

 

  9、drawRoundRect画圆角矩形

    (1)函数原型:drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)。

    (2)该函数的参数、作用、构造函数等可以参看矩形的绘制。不同点是多了rx和ry,它们表示顶点圆角的X轴方向半径和Y轴方向半径。

    (3)示例

1 canvas.drawRoundRect(100, 100, 500, 300, 50, 50, paint);

    (4)效果

 

  10、drawArc画弧线或扇形

    (1)函数原型:drawArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean useCenter, @NonNull Paint paint)。扇形或者弧线,都是椭圆(圆可以看成是椭圆的特殊情形)上的一部分,所以画扇形或者弧线需要先确定好椭圆,前4个参数就是用于确定这个椭圆。startAngle表示起始角度,X轴正方向(即水平向右方向)为0度,顺时针为正角度,逆时针为负角度。sweepAngle表示弧线/扇形划过的角度,依然是顺时针为正,逆时针为负;useCenter表示是否连到圆心,true表示连到,表示扇形,false表示不连到,表示弧线。

    (2)示例:

1  canvas.drawArc(200, 100, 800, 500, -110, 100, true, paint); // 绘制扇型
2  canvas.drawArc(200, 100, 800, 500, 20, 140, false, paint); // 绘制弧形

    (3)效果

 

  11、drawPath画自定图形

    (1)函数原型:drawPath(Path path, Paint paint) 

    (2)根据path定义的形状来绘制。这个会在后续文章中详细讲。

 

  12、drawBitmap

    (1)函数原型:drawBitmap(Bitmap bitmap, float left, float top, Paint paint)。参数bitmap表示要绘制的图片对象;left,top表示要显示的bitmap对象的左上角左边位置。

    (2)作用:把指定的bitmap对象中的像素复制到指定位置。

    (3)示例:

1 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.test);
2 canvas.drawBitmap(bitmap,100,50,paint);

    (4)效果

    (5)重载方法

          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);

       它们可以指定复制原bitmap中的指定区域(Rect src来确定),到画布中的指定位置(Rect dst)来确定。

 

  13、drawText绘制文字

        函数原型:drawText(String text, float x, float y, Paint paint)。界面里所有的显示内容,都是绘制出来的,包括文字。 drawText() 这个方法就是用来绘制文字的。参数 text 是用来绘制的字符串, x 和 y 是绘制的起点坐标。文字的绘制在后面也会单独详细说明。

 

三、Canvas实现裁剪

       根据给定的范围,对指定的bitmap进行裁剪,裁剪之后再进行绘制。范围裁剪有两个方法:clipRect()和clipPath()。前者会截取一个矩形范围,而后者path指定的形状更多,所以裁剪的形状也会更多。

  1、Canvas.save()和Canvas.restore()

       在裁剪的过程中,要加上这两句代码。它们用于保存和恢复绘制范围,如果不加容易出现干扰。

  2、clipRect()

1 canvas.save();
2 //目标bitmap
3 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.test);
4 //确定需要裁剪的矩形范围
5 canvas.clipRect(left, top, right, bottom);
6 //在指定的x,y坐标开始绘制裁剪后的bitmap
7 canvas.drawBitmap(bitmap, x, y, paint);
8 canvas.restore();

 裁剪后的效果如下图所示:

 

  3、clipPath()

      Canvas.clipRect(Path path) 用法完全一样,只是把参数换成了 Path ,所以能裁切的形状更多一些。其对应有一个方法Canvas.clipOutPaht(Path path),反向裁剪,效果可以从截图中看出来。

canvas.save();
canvas.clipPath(path1);
canvas.drawBitmap(bitmap, point1.x, point1.y, paint);
canvas.restore();
canvas.save();
canvas.clipOutPath(path);
canvas.drawBitmap(bitmap, point2.x, point2.y, paint);
canvas.restore();

这个功能对显示原型头像比较有帮助。

 

四、Canvas实现几何变换

       几何变换的使用大概分为三类:使用 Canvas 来做常见的二维变换;使用 Matrix 来做常见和不常见的二维变换;使用 Camera 来做三维变换。

 

  1、使用 Canvas 来做常见的二维变换

    (1)Canvas.translate(float dx, float dy) 平移。参数里的  dx 和  dy 表示横向和纵向的位移。

    (2)Canvas.rotate(float degrees, float px, float py) 旋转

    (3)Canvas.scale(float sx, float sy, float px, float py)放大缩小

    (4)Canvas.skew(float sx, float sy) 错切,就是倾斜的意思。

 1 canvas.save();
 2 //水平向X轴正方向移动200px
 3 canvas.translate(200, 0);
 4 //以给定的点为轴旋转45度
 5 canvas.rotate(45, centerX, centerY);
 6 //以图片中心为轴,水平和竖直方向各放大为原来的1.3倍
 7 canvas.scale(1.3f, 1.3f, x + bitmapWidth / 2, y + bitmapHeight / 2);
 8 canvas.skew(0, 0.5f);
 9 canvas.drawBitmap(bitmap, x, y, paint);
10 canvas.restore();

 

  2、使用 Matrix 来做变换

       使用Matrix可以做常规的几何变换,还可以对图形进行自定义变换。在做常规的几何变换时,和前面介绍的用Canvas实现常规变换,功能一样,选其一即可。

    (1)使用Matrix做常规变换

       使用Matrix 来做常规变换主要分三个步骤(1)创建Matrix对象;(2)Matrix.pre/postTranslate/Rotate/Scale/Skew()设置几何变换;(3)Canvas.setMatrix(matrix)或Canvas.concat(matrix)把几何变换应用到Canvas中(尽量用后者)。

 1 //1.创建Matrix对象
 2 Matrix matrix = new Matrix();
 3 matrix.reset();
 4 //2.几何变换
 5 matrix.postTranslate(0,100);
 6 matrix.postRotate(45,bitmap.getWidth()/2,bitmap.getHeight()/2);
 7 matrix.postScale(1.3f,1.3f,x+bitmap.getWidth()/2,y+bitmap.getHeight()/2);        
 8 matrix.postSkew(0,0.5f);
 9 canvas.save();
10 //3.把几何变换应用到Canvas中
11 canvas.concat(matrix);
12 canvas.drawBitmap(bitmap,x,y,paint1);
13 canvas.restore();

    (2)使用Matrix做自定义变换

       使用Maxtrix做自定义变换,可以对图形进行任意拉伸,如下图所示:

       这需要用到Matrix提供的setPolyToPoly方法来实现,具体的使用这里不做介绍,请查阅【个人记录 View Matrix setPolyToPoly】。

 

  3、使用 Camera 来做三维变换

       这一块没有使用过,这里不做介绍,知道有这个功能即可。

 

结语

       本文主要就是记录和梳理学习Canvas中的一些要点,非常基础,但都实用和常见。内容的来源是腾讯课堂中“仍物线学堂”中课件,特在此声明。

 

转载于:https://www.cnblogs.com/andy-songwei/p/10960012.html

这篇关于【朝花夕拾】Android自定义View篇之(二)Canvas常用功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/251136

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

常用的jdk下载地址

jdk下载地址 安装方式可以看之前的博客: mac安装jdk oracle 版本:https://www.oracle.com/java/technologies/downloads/ Eclipse Temurin版本:https://adoptium.net/zh-CN/temurin/releases/ 阿里版本: github:https://github.com/

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

30常用 Maven 命令

Maven 是一个强大的项目管理和构建工具,它广泛用于 Java 项目的依赖管理、构建流程和插件集成。Maven 的命令行工具提供了大量的命令来帮助开发人员管理项目的生命周期、依赖和插件。以下是 常用 Maven 命令的使用场景及其详细解释。 1. mvn clean 使用场景:清理项目的生成目录,通常用于删除项目中自动生成的文件(如 target/ 目录)。共性规律:清理操作