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

原创 2016年05月31日 16:34:44

笔记

尺寸单位转换

   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群英传》读书笔记(6)第六章:Android绘图机制与处理技巧之二

1.色彩特效处理1.色彩矩阵分析在色彩处理中通常从下面三个角度描述一个图像: 色调——物体传播的颜色 饱和度——颜色的纯度,从0(灰)到100%(饱和)来进行描述 亮度——颜色的相对明暗度 Andro...

《Android群英传》读书笔记(7)第六章:Android绘图机制与技巧之三

1.SurfaceView 一般的View通过刷新来重绘视图,Android系统通过发出VSYNC信号来进行屏幕的重绘,刷新的时间间隔是16ms。如果在16ms内View完成了所需要执行的操作,那么用...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

《Android群英传》读书笔记6.Android绘图机制与处理技巧

1. 屏幕的尺寸信息1.1. 屏幕参数 屏幕大小:指屏幕对角线的长度,例如4.7寸手机、5.5寸手机 分辨率:指手机屏幕的像素点个数,例如720×1280,指宽有720个像素点,而高有1280个像素点...

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

本章将介绍关于Andorid绘图机制的一些高级技巧与分析 6.1、屏幕的尺寸信息 一般我们以720x1280为标准原稿,那么1dp = 2px 6.2、2D绘图基础 Canvas提供了很多ap...

《Android群英传》读书笔记(8)第七章:Android动画机制与使用技巧

1.视图动画 Android视图动画的分类: 透明度动画——AlphaAnimation旋转动画——RotateAnimation位移动画——TranslateAnimation缩放动画——Sca...

Android群英传读书笔记-2D绘图基础

系统通过 Canvas 为我们提供了一些基础的绘图 API :   canvas.drawPoint(float x, float y, @NonNull Paint paint); 作用:绘制点...
  • zone_
  • zone_
  • 2017-04-22 16:23
  • 250
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)