最早在git上发现一个非常酷眩的动绘图标效果:
不得不说,国外的程序猿在细节的考虑上,确实比我们要好非常多,ok,今天我们就来模仿下这个:
现来看看我们的效果,别喷我,就写了个把小时,非常多细节还没考虑全,代码也还没重构,希望大家能提出改动意见,thx~
gif效果不一定好,大家能够參考github的gif。
代码例如以下:
首先我们要来了解下原理:
1、我们首先来确定一些关键点的坐标,也就是我们要显示的图形的全部出现的顶点
2、线条的移动效果,我们使用属性动画来控制,不熟悉的朋友能够看看,通过这个样例大家应该会对属性动画有更深的理解了
3、对于没有提供get、set方法的属性,我们通过重写Property来帮助这个属性添加get、set方法
了解了以上内容,就能够来看详细的代码了:
package com.example.yishengxu.canvas;import android.animation.ObjectAnimator;import android.animation.TypeEvaluator;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PointF;import android.util.AttributeSet;import android.util.Property;import android.view.MotionEvent;import android.view.View;import java.util.ArrayList;import java.util.List;/** * Created by yisheng.xu on 10/30/14. */public class CanvasView extends View { private float mPaddingW; private float mPaddingH; private float mRotation; private List布局文件和主文件非常easy:mAllPoints = new ArrayList (); private PointF mPoint0; private PointF mPoint1; private PointF mPoint2; private PointF mPoint3; private PointF mPoint4; private PointF mPoint5; private PointF mPoint6; private PointF mPoint7; private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private int touchFlag = 0; public CanvasView(Context context) { super(context); } public CanvasView(Context context, AttributeSet attrs) { super(context, attrs); } public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { mPaddingW = w / 4; mPaddingH = h / 4; mAllPoints.add(new PointF(mPaddingW, mPaddingH)); mAllPoints.add(new PointF(mPaddingW * 3, mPaddingH)); mAllPoints.add(new PointF(mPaddingW, mPaddingH * 2)); mAllPoints.add(new PointF(mPaddingW * 3, mPaddingH * 2)); mAllPoints.add(new PointF(mPaddingW, mPaddingH * 3)); mAllPoints.add(new PointF(mPaddingW * 3, mPaddingH * 3)); mAllPoints.add(new PointF(mPaddingW * 2, mPaddingH)); mAllPoints.add(new PointF(mPaddingW * 2, mPaddingH * 3)); initPoints(); mPaint.setColor(Color.BLUE); mPaint.setStrokeWidth(20); mPaint.setStrokeCap(Paint.Cap.ROUND); super.onSizeChanged(w, h, oldw, oldh); } private void initPoints() { mPoint0 = new PointF(mAllPoints.get(0).x, mAllPoints.get(0).y); mPoint1 = new PointF(mAllPoints.get(1).x, mAllPoints.get(1).y); mPoint2 = new PointF(mAllPoints.get(2).x, mAllPoints.get(2).y); mPoint3 = new PointF(mAllPoints.get(3).x, mAllPoints.get(3).y); mPoint4 = new PointF(mAllPoints.get(4).x, mAllPoints.get(4).y); mPoint5 = new PointF(mAllPoints.get(5).x, mAllPoints.get(5).y); mPoint6 = new PointF(); mPoint7 = new PointF(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.rotate(180 * mRotation, mPaddingW * 2, mPaddingH * 2); drawLine(canvas, mPoint0, mPoint1); drawLine(canvas, mPoint2, mPoint3); drawLine(canvas, mPoint4, mPoint5); drawLine(canvas, mPoint6, mPoint7); canvas.restore(); } private void drawLine(Canvas canvas,PointF start,PointF end) { if (start.x!=0 && end.x !=0) { canvas.drawLine(start.x, start.y, end.x, end.y, mPaint); } } @Override public boolean onTouchEvent(MotionEvent event) { if (touchFlag == 0) { animPoints(mPoint0, mAllPoints.get(2)); animPoints(mPoint4, mAllPoints.get(2)); animPoints(mPoint1, mAllPoints.get(6)); animPoints(mPoint5, mAllPoints.get(7)); touchFlag += 1; }else if (touchFlag == 1) { resetPoints(); touchFlag += 1; }else if (touchFlag == 2) { animPoints(mPoint0, mAllPoints.get(4)); animPoints(mPoint4, mAllPoints.get(0)); mPoint2 = new PointF(0, 0); mPoint3 = new PointF(0, 0); invalidate(); touchFlag += 1; } else if (touchFlag == 3) { resetPoints(); touchFlag += 1; } else { animPoints(mPoint0, mAllPoints.get(6)); animPoints(mPoint1, mAllPoints.get(3)); animPoints(mPoint5, mAllPoints.get(6)); mPoint2 = new PointF(0, 0); mPoint3 = new PointF(0, 0); invalidate(); touchFlag = 1; } return super.onTouchEvent(event); } private void resetPoints() { animPoints(mPoint0, mAllPoints.get(0)); animPoints(mPoint1, mAllPoints.get(1)); animPoints(mPoint2, mAllPoints.get(2)); animPoints(mPoint3, mAllPoints.get(3)); animPoints(mPoint4, mAllPoints.get(4)); animPoints(mPoint5, mAllPoints.get(5)); } private void animPoints(final PointF start, final PointF end) { ValueAnimator animator = ValueAnimator.ofObject(new TypeEvaluator () { @Override public PointF evaluate(float v, PointF o, PointF o2) { start.x = start.x + (end.x - start.x) * v; start.y = start.y + (end.y - start.y) * v; invalidate(); return null; } }, start, end); animator.setDuration(1000); animator.start(); ObjectAnimator animator1 = ObjectAnimator.ofFloat(this, mRotationProperty, 0, 1F); animator1.setDuration(500); animator1.start(); } private Property mRotationProperty = new Property (Float.class, "rotation") { @Override public Float get(CanvasView object) { return object.mRotation; } @Override public void set(CanvasView object, Float value) { object.mRotation = value; } };}
package com.example.yishengxu.canvas;import android.app.Activity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}OK,关键还是要有脑子,有idea,在现有知识的基础上,加工、创造。
如今,5.0来了,新增了Vector Drawable,以及对SVG的支持,让我们对实现更复杂的路径轨迹动画效果,有了更强大的工具。
最后,打个广告——友情链接 ~非常好的,说科技、聊电影、游戏,真独立,非客观,第三方.
以上。