Android群英传读书笔记第六章(Android绘图机制与处理技巧)

本文主要是介绍Android群英传读书笔记第六章(Android绘图机制与处理技巧),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

笔记

尺寸单位转换

   public static int dp2px(int dp, Context context) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,context.getResources().getDisplayMetrics());}public static int dip2px(int dip,Context context){float scale = context.getResources().getDisplayMetrics().density;return (int) (dip*scale+0.5f);}public static int sp2px(int sp,Context context){float scale = context.getResources().getDisplayMetrics().scaledDensity;return (int) (sp*scale+0.5f);}

Android绘图
先看下Canvas的操作

  • save():将所有之前绘制的图像保存起来,让后续的操作好像在一个新的图层一样
  • restore():将save之后绘制的图像和save之前的图像合并。
  • translate()和rotate():画布平移旋转,也可以理解过坐标的平移旋转,这样更加好理解。

    接下来我们绘制一个表盘。
    这里写图片描述

public class ClockView extends View {Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);Paint degreePaint = new Paint(Paint.ANTI_ALIAS_FLAG);Paint hourPaint = new Paint(Paint.ANTI_ALIAS_FLAG);Paint minutePaint = new Paint(Paint.ANTI_ALIAS_FLAG);private int height;private int width;public ClockView(Context context, AttributeSet attrs) {super(context, attrs);init();}public void init(){circlePaint.setStyle(Paint.Style.STROKE);circlePaint.setStrokeWidth(5);circlePaint.setColor(Color.RED);hourPaint.setStrokeWidth(10);minutePaint.setStrokeWidth(8);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);height = getMeasuredHeight();width = getMeasuredWidth();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawCircle(width/2,height/2,width/2,circlePaint);drawDegree(canvas);drawHourAndMinute(canvas);}private void drawHourAndMinute(Canvas canvas) {canvas.save();canvas.translate(width/2,height/2);canvas.drawLine(0,0,100,100,hourPaint);canvas.drawLine(0,0,200,100,minutePaint);canvas.drawRect(0,0,20,20,hourPaint);canvas.restore();}public void drawDegree(Canvas canvas){for (int i = 0; i < 24; i++) {if(i==0||i==6||i==12||i==18){degreePaint.setStrokeWidth(5);degreePaint.setTextSize(30);canvas.drawLine(width/2,height/2-width/2,width/2,height/2 - width/2+60,degreePaint);String degree = String.valueOf(i);canvas.drawText(degree,width/2-degreePaint.measureText(degree)/2,height/2-width/2+90,degreePaint);}else{degreePaint.setStrokeWidth(3);degreePaint.setTextSize(20);canvas.drawLine(width/2,height/2-width/2,width/2,height/2 - width/2+30,degreePaint);String degree = String.valueOf(i);canvas.drawText(degree,width/2-degreePaint.measureText(degree)/2,height/2-width/2+60,degreePaint);}canvas.rotate(15,width/2,height/2);}}
}

Layer图层
通过saveLayer()来创建一个图层,基于栈的结构进行管理。
相关方法:
saveLayer();
saveLayerAlpha()
restore:()
restoreToCount()

色彩特效处理
这里写图片描述

变换颜色值的两种方法

  • 改变偏移量
  • 改变颜色系数

    颜色效果处理

  • 色调:matrix.setRotate();

  • 饱和度:matrix.setSaturation();
  • 亮度:matrix.setScale();

Android系统不允许修改原图,要先创建一个原图的副本,然后利用这个副本创建一个画布,最后把原图绘制到画布中。

  Bitmap bmp = Bitmap.createBitmap(bm.getWidth(),bm.getHeight(), Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bmp);Paint paint  = new Paint();canvas.drawBitmap(bm,0,0,paint);

通过ColorMatrix的set方法,可以将一个一维数组转化为ColorMatrix
这里写图片描述

Android图形处理
Android的图形变换是一个3X3的矩阵,图形变化的初始矩阵也是对角线全部为1的矩阵

图形变化包含下面四个基本操作

  • 平移
  • 旋转
  • 缩放
  • 错切

Shader
- BitmapShader
- LinearGradient
- RadiaGradient
- SweepGradient
- ComposeShader

填充模式

  • CLAMP:拉伸,拉伸的是图片的最后一个像素,不断重复
  • REPEAT:重复:横向,纵向不断重复
  • MIRROR:镜像:横向不断重复旋转,纵向不断重复旋转

    SurfaceView
    Android系统通过发出VSYNC信号来进行屏幕的重绘,刷新的时间间隔为16ms.

SurfaceView和View的区别
- View主要适用于主动更新情况,而SurfaceView主要适用于被动更新,例如频繁的刷新
- View在主线程中对画面刷新,而SurfaceView会通过一个子线程来刷新
- SurfaceView在底层实现了双缓冲机制
- 当程序需要更新View上的图像时,程序必须重绘View上显示的整张图片

如果你的自定义View需要频繁刷新,或者刷新时数据量比较大,就可以使用SurfaceView了。下面来看两个SurfaceView的例子

绘制正弦曲线

这里写图片描述

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable {private SurfaceHolder surfaceHolder;private Canvas canvas;private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);//控制子线程private boolean mIsDrawing;private int x = 0;private int y;private Path mPath = new Path();public MySurfaceView(Context context, AttributeSet attrs) {super(context, attrs);surfaceHolder = getHolder();surfaceHolder.addCallback(this);setFocusable(true);setFocusableInTouchMode(true);setKeepScreenOn(true);paint.setColor(Color.RED);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(5);}/*** surfaceview创建* @param holder*/@Overridepublic void surfaceCreated(SurfaceHolder holder) {mIsDrawing = true;new Thread(this).start();}/*** surfaceview改变* @param holder* @param format* @param width* @param height*/@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}/*** surfaceview销毁* @param holder*/@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {mIsDrawing = false;}@Overridepublic void run() {while(mIsDrawing){draw();x+=1;y = (int) (100*Math.sin(x*2*Math.PI/180)+400);mPath.lineTo(x,y);}}public void draw(){try {canvas = surfaceHolder.lockCanvas();//设置画布背景颜色canvas.drawColor(Color.WHITE);canvas.drawPath(mPath,paint);}catch (Exception e){}finally {//对画布内容进行提交,放在finally里面可以保证执行if(canvas!=null){surfaceHolder.unlockCanvasAndPost(canvas);}}}
}

画布

这里写图片描述

public class SurfaceViewCanvas extends SurfaceView implements SurfaceHolder.Callback,Runnable {private SurfaceHolder mHolder;private Canvas canvas;private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);private boolean mIsDrawing;private Path mPath = new Path();public SurfaceViewCanvas(Context context, AttributeSet attrs) {super(context, attrs);mHolder = getHolder();mHolder.addCallback(this);setFocusable(true);setFocusableInTouchMode(true);setKeepScreenOn(true);paint.setColor(Color.RED);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(10);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {mIsDrawing = true;}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {new Thread(this).start();}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {mIsDrawing =false;}@Overridepublic void run() {long start = System.currentTimeMillis();while(mIsDrawing){draw();}long end = System.currentTimeMillis();if(end - start <100){try {Thread.sleep(100-(end - start));} catch (InterruptedException e) {e.printStackTrace();}}}private void draw(){try {canvas = mHolder.lockCanvas();canvas.drawColor(Color.WHITE);canvas.drawPath(mPath,paint);}catch (Exception e){}finally {if(canvas!=null){mHolder.unlockCanvasAndPost(canvas);}}}@Overridepublic boolean onTouchEvent(MotionEvent event) {int x = (int) event.getX();int y = (int) event.getY();switch (event.getAction()){case MotionEvent.ACTION_DOWN:mPath.moveTo(x,y);break;case MotionEvent.ACTION_MOVE:mPath.lineTo(x,y);break;case MotionEvent.ACTION_UP:break;}return true;}
}

与上一个例子不同的地方在于,我们对绘制的频率进行了限制,因为我们有时候不需要很频繁的绘制,这里的100mx是一个大致的经验证,这个值的范围一般在50ms到100mx之间。

这篇关于Android群英传读书笔记第六章(Android绘图机制与处理技巧)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

JAVA线程的周期及调度机制详解

《JAVA线程的周期及调度机制详解》Java线程的生命周期包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,线程调度依赖操作系统,采用抢占... 目录Java线程的生命周期线程状态转换示例代码JAVA线程调度机制优先级设置示例注意事项JAVA线程

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求

Java中自旋锁与CAS机制的深层关系与区别

《Java中自旋锁与CAS机制的深层关系与区别》CAS算法即比较并替换,是一种实现并发编程时常用到的算法,Java并发包中的很多类都使用了CAS算法,:本文主要介绍Java中自旋锁与CAS机制深层... 目录1. 引言2. 比较并交换 (Compare-and-Swap, CAS) 核心原理2.1 CAS

SpringSecurity中的跨域问题处理方案

《SpringSecurity中的跨域问题处理方案》本文介绍了跨域资源共享(CORS)技术在JavaEE开发中的应用,详细讲解了CORS的工作原理,包括简单请求和非简单请求的处理方式,本文结合实例代码... 目录1.什么是CORS2.简单请求3.非简单请求4.Spring跨域解决方案4.1.@CrossOr

Spring Boot 集成 mybatis核心机制

《SpringBoot集成mybatis核心机制》这篇文章给大家介绍SpringBoot集成mybatis核心机制,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值... 目录Spring Boot浅析1.依赖管理(Starter POMs)2.自动配置(AutoConfigu

requests处理token鉴权接口和jsonpath使用方式

《requests处理token鉴权接口和jsonpath使用方式》文章介绍了如何使用requests库进行token鉴权接口的处理,包括登录提取token并保存,还详述了如何使用jsonpath表达... 目录requests处理token鉴权接口和jsonpath使用json数据提取工具总结reques

2025最新版Android Studio安装及组件配置教程(SDK、JDK、Gradle)

《2025最新版AndroidStudio安装及组件配置教程(SDK、JDK、Gradle)》:本文主要介绍2025最新版AndroidStudio安装及组件配置(SDK、JDK、Gradle... 目录原生 android 简介Android Studio必备组件一、Android Studio安装二、A

C# 空值处理运算符??、?. 及其它常用符号

《C#空值处理运算符??、?.及其它常用符号》本文主要介绍了C#空值处理运算符??、?.及其它常用符号,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录一、核心运算符:直接解决空值问题1.??空合并运算符2.?.空条件运算符二、辅助运算符:扩展空值处理