標籤:android開發 動畫 軌跡 路徑 動態動畫
最早在git上發現一個很酷眩的動畫表徵圖效果:
https://github.com/xuyisheng/tickplusdrawable
不得不說,國外的程式員在細節的考慮上,確實比我們要好很多,ok,今天我們就來模仿下這個:
現來看看我們的效果,別噴我,就寫了個把小時,很多細節還沒考慮全,代碼也還沒重構,希望大家能提出修改意見,thx~
gif效果不一定好,大家可以參考github的gif。
代碼如下:
首先我們要來瞭解下原理:
1、我們首先來確定一些關鍵點的座標,也就是我們要顯示的圖形的所有出現的頂點
2、線條的移動效果,我們使用屬性動畫來控制,不熟悉的朋友可以看看http://blog.csdn.net/eclipsexys/article/details/38401641,通過這個例子大家應該會對屬性動畫有更深的理解了
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<PointF> mAllPoints = new ArrayList<PointF>(); 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<PointF>() { @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<CanvasView, Float> mRotationProperty = new Property<CanvasView, Float>(Float.class, "rotation") { @Override public Float get(CanvasView object) { return object.mRotation; } @Override public void set(CanvasView object, Float value) { object.mRotation = value; } };}
布局檔案和主檔案很簡單:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="50dp" android:paddingRight="50dp" android:paddingTop="150dp" android:paddingBottom="150dp" tools:context=".MainActivity"> <view android:layout_width="wrap_content" android:layout_height="wrap_content" class="com.example.yishengxu.canvas.CanvasView" android:id="@+id/view" android:layout_alignParentStart="true" /></RelativeLayout>
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的支援,讓我們對實現更複雜的路徑軌跡動畫效果,有了更強大的工具。
最後,打個廣告——友情連結 HZTalk~非常好的,說科技、聊電影、遊戲,真獨立,非客觀,第三方.
以上。
Android動畫表徵圖——I am not a gif maker,I am a developer