码迷,mamicode.com
首页 > 其他好文 > 详细

Path动画--书写文字的动画实现

时间:2015-01-29 17:52:51      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:android   path   

国际惯例,先看一下效果:屏幕上手写一些文字,然后让手机按照你的笔画顺序在屏幕上画出来一模一样的文字。

技术分享


分析下实现原理:写一个类复写View,捕获onTouch事件;→处理这个事件,事件发生的坐标分别存放在一个集合和一个path中,path用于实时绘制,集合用于稍后动画绘制,按下事件path.moveTo,抬起path.lineTo;→手指抬起1s内不再按下则让手机自动绘制我们的文字。

一些实现细节:

1,设置画笔的一些属性,给定颜色,给定笔尖粗细,笔尖形状,抗锯齿等。

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(STROKE_WIDTH);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setColor(PAINT_COLOR);

2,一些变量

  public final float STROKE_WIDTH = 10;//笔尖宽度
    public final int PAINT_COLOR = Color.GRAY;//画笔颜色
    ArrayList<ArrayList<PathPoint>> lines;//存放所有线
    Paint paint;
    ArrayList<PathPoint> line;//一条线即手指按下到抬起一个完整路径
    //ondraw中绘制用的path
    Path path;
    //触屏最后一次得到的点
    private PathPoint point = new PathPoint(0, 0);
    private boolean isTouching = false;//是不是正在用手指画
    private long upTime;//手指抬起的时刻
    private boolean isDrawing;//是不是在自动画

3,封装一个PathPoint类方便管理坐标

    class PathPoint {
        PathPoint(float x, float y) {
            this.x = x;
            this.y = y;
        }

        float x, y;

        /**
         * 到点p的距离
         *
         * @param p
         * @return
         */
        public double lenthToPoint(PathPoint p) {
            float f = (p.x - x) * (p.x - x) + (p.y - y) * (p.y - y);
            return Math.sqrt(f);
        }
    }

4,处理onTouch事件:主要是实时画线和储存待会儿自动画线的数据,记录手指抬起的时间,后边会做一个判断什么时候开始自动画线。

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isDrawing) return true;
        PathPoint pathPoint;
        pathPoint = getEventPoint(event);
        if (pathPoint.lenthToPoint(point) < 1) return true;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                path.moveTo(pathPoint.x, pathPoint.y);
                line = new ArrayList<PathPoint>();
                isTouching = true;
                break;
            case MotionEvent.ACTION_UP:
                lines.add(line);
                isTouching = false;
                upTime = System.currentTimeMillis();

                autoDraw();
            default:
                path.lineTo(pathPoint.x, pathPoint.y);
                break;
        }
        line.add(pathPoint);
        invalidate();
        return true;
    }

5,开始自动画线

  @Override
    public void run() {
        while (System.currentTimeMillis() - upTime < 1000) {//手指抬起够不够1s,不够返回
            if (isTouching) return;
        }
        isDrawing = true;
        Log.i("info", "你倒是画啊,线数:" + lines.size());
        path = new Path();
        for (int i = 0; i < lines.size(); i++) {
            ArrayList<PathPoint> l = lines.get(i);
            Log.i("info", "点数:" + l.size());
            for (int j = 0; j < l.size(); j++) {
                PathPoint p = l.get(j);
                if (j == 0) path.moveTo(p.x, p.y);
                else path.lineTo(p.x, p.y);
                postInvalidate();
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
<span style="white-space:pre">	</span>//复原
        lines.clear();
        line.clear();
        path = new Path();
        isDrawing = false;

    }

完整代码:

package com.sovnem.administrator.boxmenu;

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.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;

/**
 * Created by Sovnem on 2015/1/29.
 */
public class PathAnimationView extends View implements Runnable {
    public final float STROKE_WIDTH = 10;//笔尖宽度
    public final int PAINT_COLOR = Color.GRAY;//画笔颜色
    ArrayList<ArrayList<PathPoint>> lines;//存放所有线
    Paint paint;
    ArrayList<PathPoint> line;//一条线即手指按下到抬起一个完整路径
    //ondraw中绘制用的path
    Path path;
    //触屏最后一次得到的点
    private PathPoint point = new PathPoint(0, 0);
    private boolean isTouching = false;//是不是正在用手指画
    private long upTime;//手指抬起的时刻
    private boolean isDrawing;//是不是在自动画

    public PathAnimationView(Context context) {
        super(context);
        init();
    }

    public PathAnimationView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PathAnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void init() {
        paint = new Paint();
        paint.setStrokeWidth(STROKE_WIDTH);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setColor(PAINT_COLOR);
        lines = new ArrayList<>();
        path = new Path();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        canvas.drawPath(path, paint);
    }



    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isDrawing) return true;
        PathPoint pathPoint;
        pathPoint = getEventPoint(event);
        if (pathPoint.lenthToPoint(point) < 1) return true;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                path.moveTo(pathPoint.x, pathPoint.y);
                line = new ArrayList<PathPoint>();
                isTouching = true;
                break;
            case MotionEvent.ACTION_UP:
                lines.add(line);
                isTouching = false;
                upTime = System.currentTimeMillis();

                autoDraw();
            default:
                path.lineTo(pathPoint.x, pathPoint.y);
                break;
        }
        line.add(pathPoint);
        invalidate();
        return true;
    }

    private void autoDraw() {
        new Thread(this).start();

    }

    @Override
    public void run() {
        while (System.currentTimeMillis() - upTime < 1000) {
            if (isTouching) return;
        }
        isDrawing = true;
        Log.i("info", "你倒是画啊,线数:" + lines.size());
        path = new Path();
        for (int i = 0; i < lines.size(); i++) {
            ArrayList<PathPoint> l = lines.get(i);
            Log.i("info", "点数:" + l.size());
            for (int j = 0; j < l.size(); j++) {
                PathPoint p = l.get(j);
                if (j == 0) path.moveTo(p.x, p.y);
                else path.lineTo(p.x, p.y);
                postInvalidate();
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        lines.clear();
        line.clear();
        path = new Path();
        isDrawing = false;

    }

    private PathPoint getEventPoint(MotionEvent event) {

        return new PathPoint(event.getX(), event.getY());
    }

    class PathPoint {
        PathPoint(float x, float y) {
            this.x = x;
            this.y = y;
        }

        float x, y;

        /**
         * 到点p的距离
         *
         * @param p
         * @return
         */
        public double lenthToPoint(PathPoint p) {
            float f = (p.x - x) * (p.x - x) + (p.y - y) * (p.y - y);
            return Math.sqrt(f);
        }
    }
}


。。。回头看了看有点水啊,全是代码。

那么,说点更水的:

可以自己在手机上给你的手机应用写点关键文字,在上边的代码里加点方法,把得到的坐标保存到本地,数据库、文件随你,在你的引用引导页中加载这些数据,然后在一笔一笔的把字写在手机屏幕上,是不是有种电影高大上的效果。

手机上的svg动画的原理也大概如此吧,svg也是包含了一大堆点坐标,github有很多关于svg动画的项目。淘宝手机app第一次进入开场那个动画想着应该是svg之类吧,不过那个炫酷多了,有兴趣可以研究一下。

也可以把你想对女神说的话以这种方式记录出来,假装给她测试应用,不经意间show给她看。

恩。。。效率是什么东西?

以上,纯玩。


Path动画--书写文字的动画实现

标签:android   path   

原文地址:http://blog.csdn.net/u012293381/article/details/43272171

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!