Android之绘图

一直对画画相关不感冒,但是Android的绘图机制还是要硬着头皮学

绘画主要是使用paint(画笔)在canvas(画布)进行各种图形的绘制,画矩形、圆、三角形等点线构成的2维图形

//矩形  drawRect (float left, float top, float right, float bottom, Paint paint)
        canvas.drawRect(50, 100, 200, 200, paint);

        //圆  drawCircle (float cx, float cy, float radius, Paint paint)
        canvas.drawCircle(width / 2, height / 2, 100, paint);

        //三角形(画线)
        //实例化路径
        Path path = new Path();
        path.moveTo(80, 300);// 此点为多边形的起点
        path.lineTo(120, 250);
        path.lineTo(80, 250);
        path.close(); // 使这些点构成封闭的多边形
        canvas.drawPath(path, paint);

        //扇形 RectF (float left, float top, float right, float bottom)
        RectF rectF = new RectF(160, 200, 400, 400);
        // drawArc (RectF oval, float startAngle 起始弧度, float sweepAngle 扫过的弧度, boolean useCenter, Paint paint)
        canvas.drawArc(rectF, 200, 130, true, paint);

        //椭圆
        rectF = new RectF(300, 300, 600, 600);
        //  set (float left, float top, float right, float bottom)
        rectF.set(210,100,450,200);
        // drawOval (RectF oval, Paint paint)
        canvas.drawOval(rectF, paint);

        //曲线
        //设置空心
        paint.setStyle(Paint.Style.STROKE);
        path = new Path();
        path.moveTo(500, 500);//设置Path的起点
        path.quadTo(550, 510, 670, 600);  //设置路径点和终点
        canvas.drawPath(path, paint);

        //文字+ 图片
        paint.setTextSize(30);
        //文本 drawText (String text, float x, float y, Paint paint)
        canvas.drawText("slack", 350, 330, paint);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
        //图片 drawBitmap (Bitmap bitmap, float left, float top, Paint paint)
        canvas.drawBitmap(bitmap, 320, 360, paint);

canvas有几个重要的方法,画图时会使用到,类似ps里的图层,旋转,位移的概念

/*
    *  Canvas.save() 将之前的图像保存起来,让后续的操作能像在新的画布一样操作
    *  Canvas.restore() 合并图层
    *  Canvas.translate() 平移 我们绘制的时候默认坐标点事左上角的起始点,那么我们调用translate(x,y)之后,
    则将原点(0,0)移动到(x,y)之后的所有绘图都是在这一点上执行的
    *  Canvas.roate() 旋转
    * */

画一个时钟,就把这些理解了

//画时钟
        // 画外圆
        Paint paintCircle = new Paint();
        paintCircle.setAntiAlias(true);
        paintCircle.setStyle(Paint.Style.STROKE);
        paintCircle.setStrokeWidth(5);
        canvas.drawCircle(width / 2, height / 2, width / 3, paintCircle);
        // 画刻度
        Paint paintDegree = new Paint();
        paintDegree.setStrokeWidth(3);
        canvas.rotate(30, width / 2, height / 2);
        for (int i = 1; i <= 12; i++) {
            // 区别整点和非整点
            if (i == 3 || i == 6 || i == 9 || i == 12 ) {
                paintDegree.setStrokeWidth(5);
                paintDegree.setTextSize(30);
                // drawLine (float startX, float startY, float stopX, float stopY, Paint paint)
                canvas.drawLine(width / 2, height / 2 - width / 3,
                        width / 2, height / 2 - width / 3 + 60, paintDegree);
                String degree = String.valueOf(i);
                canvas.drawText(degree,
                        width / 2 - paintDegree.measureText(degree) / 3,
                        height / 2 - width / 3 + 90, paintDegree);
            } else {
                paintDegree.setStrokeWidth(3);
                paintDegree.setTextSize(15);
                // 圆上的一点(x = 屏幕宽一半, y = 屏幕的一半 - 半径)
                canvas.drawLine(width / 2, height / 2 - width / 3,
                        width / 2, height / 2 - width / 3 + 30, paintDegree);
                String degree = String.valueOf(i);
                canvas.drawText(degree,
                        width / 2 - paintDegree.measureText(degree) / 3,
                        height / 2 - width / 3 + 60, paintDegree);
            }
            // 通过旋转画布——实际上是旋转了画图的坐标轴 简化坐标运算
            canvas.rotate(30, width / 2, height / 2);
        }

        canvas.save();
        // 画指针
        Paint paintHour = new Paint();
        paintHour.setStrokeWidth(15);
        Paint paintMinute = new Paint();
        paintMinute.setStrokeWidth(10);
        //绘制的时候默认坐标点事左上角的起始点,那么我们调用translate(x,y)之后,则将原点(0,0)移动到(x,y)之后的所有绘图都是在这一点上执行的
        canvas.translate(width / 2, height / 2);
        canvas.drawPoint(0, 0, paintHour);//圆点
        canvas.drawLine(0, 0, 100, 100, paintHour);
        canvas.drawLine(0, 0, 100, -200, paintMinute);
        canvas.restore();

模拟刮刮乐

// PorterDuffXfermode 刮刮乐 通过DST_IN.SRC_IN模式来实现将一个矩形变成圆角图片的效果
        mPaint = new Paint();
        mPaint.setAlpha(0);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeWidth(50);
        mPaint.setStrokeCap(Paint.Cap.ROUND);

        mPath = new Path();
        // createBitmap (int width, int height, Bitmap.Config config)
        mFgBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mFgBitmap);
        mCanvas.drawColor(Color.GRAY);
/**
     * 触摸事件
     * 画一条透明的线  曲线
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mPath.reset();
                lastX = event.getX();
                lastY = event.getY();
                mPath.moveTo(lastX, lastY);//起点
                break;
            case MotionEvent.ACTION_UP:
                mPath.lineTo(event.getX(), event.getY());
                break;
            case MotionEvent.ACTION_MOVE:
                //移动时,记录这一次的点位置
                mPath.quadTo(lastX, lastY, event.getX(), event.getY());  //设置曲线路径点和终点
                lastX = event.getX();
                lastY = event.getY();
                break;
        }
        mCanvas.drawPath(mPath, mPaint);
        invalidate();
        return true;
    }
@Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        //刮刮乐
        canvas.drawBitmap(mFgBitmap, 0, 0, null);
    }

SurfaceView主要用于频繁刷新处,做一个画板


SurfaceView的简单使用也简单

public class SurfaView extends SurfaceView implements SurfaceHolder.Callback, Runnable 

在线程里处理绘画的事件,贴上代码

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * SurfaceView的使用
 * Created by chenling on 2016/5/9.
 * 1.View主要用于自动更新的情况下,而surfaceVicw主要适用于被动更新,例如频繁刷新
 * 2.View在主线程中刷新,而surfaceView通常会通过一 个子线程来进行页面刷新。
 * 3.View在绘制的时候没有双缓冲机制,而surfaceVicw在底层实现机制中就已经实现了双缓冲机制;
 */
public class SurfaView extends SurfaceView implements SurfaceHolder.Callback, Runnable {

    //SurfaceHolder
    private SurfaceHolder mHolder;
    //用于绘制的Canvas
    private Canvas mCanvas;
    //子线程标志位
    private boolean mIsDrawing;
    private float lastX,lastY;
    private Path mPath;
    private Paint mPaint;

    /**
     * 构造方法
     *
     * @param context
     * @param attrs
     */
    public SurfaView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mPath = new Path();
        mPaint = new Paint();
        mPaint.setStrokeWidth(20);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mHolder = getHolder();
        mHolder.addCallback(this);
        setFocusable(true);
        setFocusableInTouchMode(true);
        setKeepScreenOn(true);
    }
    // 创建
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mIsDrawing = true;
        new Thread(this).start();
    }
    // 改变
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }
    //销毁
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsDrawing = false;
    }

    @Override
    public void run() {
        while (mIsDrawing) {
            draw();
//            lastX += 1;
//            lastY = (int) (100 * Math.sin(lastX * 2 * Math.PI / 180) + 400);
//            mPath.lineTo(lastX, lastY);
        }
    }

    // 负责绘画,频繁刷新
    private void draw() {
        try {
            mCanvas = mHolder.lockCanvas();
            mCanvas.drawColor(Color.WHITE);
            mCanvas.drawPath(mPath, mPaint);
        } catch (Exception e) {

        } finally {
            if (mCanvas != null) {
                //提交
                mHolder.unlockCanvasAndPost(mCanvas);
            }
        }
    }

    /**
     * 触摸事件
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        lastX =  event.getX();
        lastY =  event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mPath.moveTo(lastX, lastY);
                break;
            case MotionEvent.ACTION_MOVE:
                mPath.lineTo(lastX,lastY);
                break;
            case MotionEvent.ACTION_UP:
                break;
        }

        return true;
    }
}

附件:源码:https://github.com/CL-window/android_paint

时间: 2024-10-08 16:42:06

Android之绘图的相关文章

Android SurfaceView 绘图覆盖刷新及脏矩形刷新方法

http://www.cnblogs.com/SkyD/archive/2010/11/08/1871423.html Android SurfaceView 绘图覆盖刷新及脏矩形刷新方法 SurfaceView在Android中用作游戏开发是最适宜的,本文就将演示游戏开发中常用的两种绘图刷新策略在SurfaceView中的实现方法. 首先我们来看一下本例需要用到的两个素材图片: bj.jpg就是一个渐变图,用作背景. question.png是一个半透明的图像,我们希望将它放在上面,围绕其圆心

Android 2D绘图解析之 Canvas,Paint

原创文章,转载请注明 ( 来自:http://blog.csdn.net/leejizhou/article/details/51524948 李济洲的博客 ) [Android 2D绘图解析]系列文章将全面介绍Android绘图相关,这篇简单介绍下如何利用Android API进行一些简单图形的绘制,绘图的前提是需要继承自View,然后重写它的onDraw(Canvas canvas) 方法即可. 首先我们新建一个类继承自View,并重写onDraw方法. package com.leejz.

Android - View绘图原理总结

原文地址:http://blog.csdn.net/xu_fu/article/details/7829721 Android系统的视图结构的设计也采用了组合模式,即View作为所有图形的基类,Viewgroup对View继承扩展为视图容器类,由此就得到了视图部分的基本结构--树形结构 View定义了绘图的基本操作 基本操作由三个函数完成:measure().layout().draw(),其内部又分别包含了onMeasure().onLayout().onDraw()三个子方法.具体操作如下:

【转】Android Canvas绘图详解(图文)

转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html Android Canvas绘图详解(图文) 泡在网上的日子 发表于 2012-12-12 20:29 第 63165 次阅读 Canvas,android 15 Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0.今天我们主要要了解的是2D相关的,如果你想看3D的话那么可以跳

从零开始学android&lt;android基本绘图.四十六.&gt;

在一般的图形绘制中用户往往只需要覆写onDraw()方法即可,可是如果要想真正的完成绘图的操作,还需要掌握四个核心的操作类: android.graphics.Bitmap:主要表示的是一个图片的存储空间,所包含的图片可以来自于文件或由程序创建: android.graphics.Paint:主要的绘图工具类,可以指定绘图的样式: android.graphics.Canvas:是一个操作绘图以及Bitmap的平台,相当于提供了一个画板的功能,在onDraw()方法的参数中也定义了此类型的参数,

Android 画布绘图

我们已经介绍了Canvas,在那里,已经学习了如何创建自己的View.在第7章中也使用了Canvas来为MapView标注覆盖. 画布(Canvas)是图形编程中一个很普通的概念,通常由三个基本的绘图组件组成: Canvas 提供了绘图方法,可以向底层的位图绘制基本图形.Paint 也称为"刷子",Paint可以指定如何将基本图形绘制到位图上.Bitmap 绘图的表面. Android绘图API支持透明度.渐变填充.圆边矩形和抗锯齿.遗憾的是,由于资源限制,它还不支持矢量图形,它使用的

Android动态绘图实现

一直想实现一个动态绘图的功能,就是那种给定几张图片之后一张张的顺序画出来.说不明白,先上效果图. 这样可以做很多东西,像百度地图的历史轨迹绘制,引导界面做类似动画效果等. 之前我考虑用SurfaceView实现这个功能,想一想,要实现这种效果,需要开启一个子线程用于控制绘制时间间隔,以达到这种渐渐绘制的效果.动手去做了,发现用SurfaceView很难实现,SurfaceView中的Canvas与View中的Canvas不同,一个不同之处是View中的Canvas是只有一张画布,然后不停的在这张

android Canvas 绘图系列(二)

这里主要讲Paint 画笔.还是搬运和翻译官方文档吧. 1.setAlpha(int a)  设置透明度,参数范围是0-255. 如需要设置改属性:建议改成(0-1),然后乘以255. 2.setColor(int color) 设置画笔颜色其中包含透明度,参数为 0xff777777类型,0x是16进制标识,后两个ff是表示透明度,后六位是颜色值 3.setARGB(int a, int r, int g, int b) 设置rgb颜色值和透明度; 第一个参数为透明度; 第二个为red色值;

Android Canvas绘图详解(图文) - 泡在网上的日子

body { font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI",Tahoma,Helvetica,Sans-Serif,"Microsoft YaHei", Georgia,Helvetica,Arial,sans-serif,宋体, PMingLiU,serif; font-size: 10.5pt; line-height: 1.5;