6.4 Android绘图技巧(Primary:四大方法&Layer)
1.Canvas的四大金刚
Canvas.save()
这个方法从字面上可以理解为保存画布,作用就是将之前的所有已绘制的图像保存起来。让后续的操作就好像在一个新的图层上操作一样,这一点与Photoshop中的图层理解基本一致。Canvas.restore()
可以理解为Photoshop中的合并图层操作,作用是将我们在save()之后绘制的所有图像与save()之前的图像进行合并。Canvas.translate()
Android默认绘图坐标零点位于屏幕左上角,那么在调用translate()之后,则将零点(0,0)移动到了(x,y)。之后所有绘图操作都将以(x,y)为原点执行。Canvas.rotate()
与translate()同理,旋转坐标系一个一定的角度。
2.Demo:仪表盘
2.1.画外圆
2.2.画刻度和刻度值
2.3.画指针
2.4.全代码和运行结果
Clock.java:
package com.yishengxu.myapplication; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; public class Clock extends View { private int mHeight, mWidth; public Clock(Context context) { super(context); } public Clock(Context context, AttributeSet attrs) { super(context, attrs); } public Clock(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDraw(Canvas canvas) { // 获取宽高参数 mWidth = getMeasuredWidth(); mHeight = getMeasuredHeight(); // 画外圆 Paint paintCircle = new Paint(); paintCircle.setStyle(Paint.Style.STROKE); paintCircle.setAntiAlias(true); paintCircle.setStrokeWidth(5); canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, paintCircle); // 画刻度 Paint painDegree = new Paint(); paintCircle.setStrokeWidth(3); for (int i = 0; i < 24; i++) { // 区分整点与非整点 if (i == 0 || i == 6 || i == 12 || i == 18) { painDegree.setStrokeWidth(5); painDegree.setTextSize(30); canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,//基线起点x mWidth / 2, mHeight / 2 - mWidth / 2 + 60,//基线起点y painDegree); String degree = String.valueOf(i);//Integer.toString(i) canvas.drawText(degree, mWidth / 2 - painDegree.measureText(degree) / 2,//measureText()在画布上输出文本之前,检查字体的宽度: mHeight / 2 - mWidth / 2 + 90, painDegree); } else { painDegree.setStrokeWidth(3); painDegree.setTextSize(15); canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2, mWidth / 2, mHeight / 2 - mWidth / 2 + 30, painDegree); String degree = String.valueOf(i); canvas.drawText(degree, mWidth / 2 - painDegree.measureText(degree) / 2, mHeight / 2 - mWidth / 2 + 60, painDegree); } // 通过旋转画布简化坐标运算 canvas.rotate(15, mWidth / 2, mHeight / 2);//二三参数为枢轴点的xy,枢轴点即旋转中心 } // 画圆心 Paint paintPointer = new Paint(); paintPointer.setStrokeWidth(30); canvas.drawPoint(mWidth / 2, mHeight / 2, paintPointer); // 画指针 Paint paintHour = new Paint(); paintHour.setStrokeWidth(20); Paint paintMinute = new Paint(); paintMinute.setStrokeWidth(10); canvas.save();//只是保存“缓冲区”绘制的内容 canvas.translate(mWidth / 2, mHeight / 2); canvas.drawLine(0, 0, 100, 100, paintHour); canvas.drawLine(0, 0, 100, 200, paintMinute); canvas.restore();//将“缓冲区”绘制的内容和已经save()的内容一同合并并保存起来,这里跟上边的save注意区分开来 } }
MainActivity.java:
package com.yishengxu.myapplication; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new Clock(this)); } }
效果图:
3.Layer图层
创建一个新的Layer到“栈”中,可以使用saveLayer(), savaLayerAlpha(), 从“栈”中推出一个Layer,可以使用restore(),restoreToCount()。但Layer入栈时,后续的DrawXXX操作都发生在这个Layer上,而Layer退栈时,就会把本层绘制的图像“绘制”到上层或是Canvas上,在复制Layer到Canvas上时,可以指定Layer的透明度
- 透明度:
- 127,半透明
- 255,完全不透明
- 0,完全透明
实例如Demo下图:
上Demo:
package com.imooc.myapplication; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MyLayer(this)); } public class MyLayer extends View { private Paint mPaint; private static final int LAYER_FLAGS = Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG;//此乃API定义的常量,ctrl+E 进入文档查看便知晓其含义 public MyLayer(Context context) { super(context); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(Color.WHITE);//背景 mPaint.setColor(Color.BLUE); canvas.drawCircle(150, 150, 100, mPaint);//“零图层” canvas.saveLayerAlpha(0, 0, 400, 400, 127, LAYER_FLAGS); mPaint.setColor(Color.RED); canvas.drawCircle(200, 200, 100, mPaint); canvas.restore(); } } }
半透明:
完全不透明: canvas.saveLayerAlpha(0, 0, 400, 400, 255, LAYER_FLAGS);
完全透明: canvas.saveLayerAlpha(0, 0, 400, 400, 0, LAYER_FLAGS);

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
[转]深入理解在Android中线程池的使用
这是一篇 写的非常用心的 博文,这里是原文地址https://blog.csdn.net/l540675759/article/details/62230562 前言 (1)本文共花费2周零3天的凌晨时光,这段时间收获很多. (2)从整理文章,作者从线程-->阻塞队列-->二进制-->线程池的内部机制,一路走来,本来是想写一篇为AsyncTask做铺垫的文章,没想到越写越多. (3)文章中如果错误,请大家及时指正,作者会及时更新. (4)希望大家能够从文章中.多多收获,迄今为止,博主最好的一篇文章,也是花了大力气最用心的一篇文章. 线程 在了解线程池之前,先给大家介绍下线程的概念: image.png 先看一个烧水的例子,图中看电视是主线,用户想在看电视的过程中去完成烧水这个操作,并且不耽误看电视,看了这张图,在去了解接下来的概念会更好的理解主线程与子线程的概念。 线程是什么? 从底层角度来说: 一个线程就是在进程中的一个单一的顺序控制流. 而单个进程可以拥有多个并发执行的任务,每个任务都好像有自己的CPU一样,而其底层的机制就是切分CPU的时间,也就是CPU将轮流给...
- 下一篇
android8.0采坑 Only fullscreen opaque activities can request orientation
android8.0采坑 Only fullscreen opaque activities can request orientation 也就是说只有全屏不透明的activity才可以设置方向,既然知道问题所在就好办了。 找到你设置透明的Activity,然后在他的theme中加入如下配置。 <item name="android:windowIsTranslucent">false</item> <item name="android:windowDisablePreview">true</item> 但是我的项目使用的是第三方的库com.ycjiang:imgepreviewlibrary:1.1.3 之前使用点击图片预览大图imgepreviewlibrary都是一次性成功的,但是今天在新的产品上使用,却一直报错,无语。没办法只能自定义activity了。 1.我们自定义一个activity, ImageLookActivity public class ImageLookActivity extends GPreviewAct...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS关闭SELinux安全模块
- CentOS8安装Docker,最新的服务器搭配容器使用
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Windows10,CentOS7,CentOS8安装Nodejs环境
- 设置Eclipse缩进为4个空格,增强代码规范