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

相关文章

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

Android Mainline基础简介

《AndroidMainline基础简介》AndroidMainline是通过模块化更新Android核心组件的框架,可能提高安全性,本文给大家介绍AndroidMainline基础简介,感兴趣的朋... 目录关键要点什么是 android Mainline?Android Mainline 的工作原理关键

Java字符串处理全解析(String、StringBuilder与StringBuffer)

《Java字符串处理全解析(String、StringBuilder与StringBuffer)》:本文主要介绍Java字符串处理全解析(String、StringBuilder与StringBu... 目录Java字符串处理全解析:String、StringBuilder与StringBuffer一、St

如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题

《如何解决idea的Module:‘:app‘platform‘android-32‘notfound.问题》:本文主要介绍如何解决idea的Module:‘:app‘platform‘andr... 目录idea的Module:‘:app‘pwww.chinasem.cnlatform‘android-32

浅析Java中如何优雅地处理null值

《浅析Java中如何优雅地处理null值》这篇文章主要为大家详细介绍了如何结合Lambda表达式和Optional,让Java更优雅地处理null值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录场景 1:不为 null 则执行场景 2:不为 null 则返回,为 null 则返回特定值或抛出异常场景

深入理解Apache Kafka(分布式流处理平台)

《深入理解ApacheKafka(分布式流处理平台)》ApacheKafka作为现代分布式系统中的核心中间件,为构建高吞吐量、低延迟的数据管道提供了强大支持,本文将深入探讨Kafka的核心概念、架构... 目录引言一、Apache Kafka概述1.1 什么是Kafka?1.2 Kafka的核心概念二、Ka

SpringRetry重试机制之@Retryable注解与重试策略详解

《SpringRetry重试机制之@Retryable注解与重试策略详解》本文将详细介绍SpringRetry的重试机制,特别是@Retryable注解的使用及各种重试策略的配置,帮助开发者构建更加健... 目录引言一、SpringRetry基础知识二、启用SpringRetry三、@Retryable注解

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

Android Studio 配置国内镜像源的实现步骤

《AndroidStudio配置国内镜像源的实现步骤》本文主要介绍了AndroidStudio配置国内镜像源的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、修改 hosts,解决 SDK 下载失败的问题二、修改 gradle 地址,解决 gradle