Android群英传读书笔记第六章(Android绘图机制与处理技巧)
来源:互联网 发布:淘宝开店推广费用 编辑:程序博客网 时间:2024/05/16 00:37
笔记
尺寸单位转换
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); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); height = getMeasuredHeight(); width = getMeasuredWidth(); } @Override protected 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 */ @Override public void surfaceCreated(SurfaceHolder holder) { mIsDrawing = true; new Thread(this).start(); } /** * surfaceview改变 * @param holder * @param format * @param width * @param height */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } /** * surfaceview销毁 * @param holder */ @Override public void surfaceDestroyed(SurfaceHolder holder) { mIsDrawing = false; } @Override public 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); } @Override public void surfaceCreated(SurfaceHolder holder) { mIsDrawing = true; } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { new Thread(this).start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { mIsDrawing =false; } @Override public 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); } } } @Override public 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群英传》读书笔记(5)第六章:Android绘图机制与处理技巧之一
- 《Android群英传》读书笔记(6)第六章:Android绘图机制与处理技巧之二
- Android群英传读书笔记第六章(Android绘图机制与处理技巧)
- 《Android群英传》读书笔记6.Android绘图机制与处理技巧
- 《Android群英传》读书笔记(7)第六章:Android绘图机制与技巧之三
- Android群英传笔记——第六章:Android绘图机制与处理技巧
- Android群英传知识点回顾——第六章:Android绘图机制与处理技巧
- 第六章Android绘图机制与处理技巧(Android群英传)
- Android群英传学习——第六章、Android绘图机制与处理技巧
- Android群英传之Android绘图机制与处理技巧
- Android群英传之Android绘图机制与处理技巧
- Android群英传学习-Android绘图机制与处理技巧
- Android群英传--绘图机制与处理技巧(一)
- Android群英传--绘图机制与处理技巧(三)
- 绘图机制与图片处理-Android群英传
- Android群英传--绘图机制和处理技巧(二)
- Android群英传--绘图机制和处理技巧(四)
- 《Android群英传》读书笔记(8)第七章:Android动画机制与使用技巧
- Middle-题目64:95. Unique Binary Search Trees II
- 从杭电OJ1219 到getchar 以及EOF
- 第十四周项目1.1—排序函数模板(冒泡法排序)
- [WFD] WFD 连接做connect和disconnect,手机概率性的没有反应以及重启
- PHP中读取文件的几个方法
- Android群英传读书笔记第六章(Android绘图机制与处理技巧)
- Android产品研发(三)-->基类Activity
- Android学习笔记六十:无线 WIFI 的13个信道频率范围
- 身份证号码图像提取--基于canny边缘检测的连通域检测算法
- Middle-题目65:34. Search for a Range
- Ubuntu配置mysql开机自动启动
- Android样式的开发:drawable汇总篇
- MATLAB的乱七八糟问题
- SQLite数据类型