Android动画图标——I am not a gif maker,I am a developer

最早在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~非常好的,说科技、聊电影、游戏,真独立,非客观,第三方.

以上。

时间: 2024-08-10 19:08:47

Android动画图标——I am not a gif maker,I am a developer的相关文章

Android动画总结系列(6)——矢量图形与矢量动画

按照我一开始的打算,上面一篇文章应该是"Android动画总结系列(5)--属性动画源码分析",不过属性动画源码分析写起来还比较复杂,因为某些原因,我把精力投入到矢量动画这块了,第5篇估计会在后面一两周写完.本篇文章,我写的是Android5.0引入的新动画效果--矢量动画,初步打算后面还会加一篇源码分析. 一.概述 1.1 简述 Android应用的不断发展带来了安装包过大的尴尬,而Android之前一直都不支持矢量图形,是引起尴尬的一个重要原因.其实Android绘制界面时也是通过

Android动画的实现 上

在Android系统中也能经常见到动画,那么如何实现动画效果呢?本文就来为大家介绍动画的实现方式. Android中动画的实现分两种方式,一种方式是补间动画Tween Animation,就是说你定义一个开始和结束,中间的部分由程序运算得到.另一种叫逐帧动画Frame Animation,就是说一帧一帧的连起来播放就变成了动画.有点Flash基础的同学理解起来会很容易.接下来我们一个一个学习. 一.补间动画Tween Animation Android中实现补间动画的思路是这样的, 1.首先用X

Android群英传知识点回顾——第七章:Android动画机制与使用技巧

7.1 Android View动画框架 7.1.1 透明度动画 7.1.2 旋转动画 7.1.3 位移动画 7.1.4 缩放动画 7.1.5 动画集合 7.2 Android属性动画分析 7.2.1 ObjectAnimator 7.2.2 PropertyValuesHolder 7.2.3 ValueAnimator 7.2.4 动画事件的监听 7.2.5 AnimatorSet 7.2.6 在XML中使用属性动画 7.2.7 View的animate方法 7.3 Android布局动画

android动画具体解释六 XML中定义动画

动画View 属性动画系统同意动画View对象并提供非常多比view动画系统更高级的功能.view动画系统通过改变绘制方式来变换View对象,view动画是被view的容器所处理的,由于View本身没有要操控的属性.结果就是View被动画了.但View对象本身并没有变化. 在Android3.0中,新的属性和对应的getter和setter方法被增加以克服此缺点. 属性动画系统能够通过改变View对象的真实属性来动画Views. 并且.View也会在其属性改变时自己主动调用invalidate(

Android开发艺术探索——第七章:Android动画深入分析

Android开发艺术探索--第七章:Android动画深入分析 Android的动画可以分成三种,view动画,帧动画,还有属性动画,其实帧动画也是属于view动画的一种,,只不过他和传统的平移之类的动画不太一样的是表现形式上有点不一样,view动画是通过对场景的不断图像交换而产生的动画效果,而帧动画就是播放一大段图片,很显然,图片多了会OOM,属性动画通过动态的改变对象的属性达到动画效果,也是api11的新特性,在低版本无法使用属性动画,但是我们依旧有一些兼容库,OK,我们还是继续来看下详细

android 动画(1) 补间动画

android动画: 3.0以前,android支持两种动画模式,tween animation,frame animation, 3.0中又引入了一个新的动画系统:property animation, 这三种动画模式在SDK中被称为 property animation,        属性动画: view animation,   补间动画:  给出两个关键帧,通过一些算法将给定属性值在给定的时间内在两个关键帧间渐变. (Tween animation) drawable animatio

android动画详解三 动画API概述

· 属性动画与view动画的不同之处 view动画系统提供了仅动画View 对象的能力,所以如果你想动画非View 对象,你就要自己实现代码. view动画系统实际上还被强制仅能对 View 的少数属性进行动画,比如缩放和旋转,而不能对背景色进行. view动画的另一个坏处是它仅修改View的绘制位置,而不是View的实际位置.例如,如果你动画一个移动穿越屏幕,button的绘制位置是正确的,但实际你可以点击它的位置却没有变,所以你必须去实现你自己的逻辑来处理它. 使用属性动画系统时,这个限制被

Android动画基础

Android动画主要有三种: 1> 视图动画,也叫Tween(补间)动画可以在一个视图容器内执行一系列简单变换(位置.大小.旋转.透明度).譬如,如果你有一个TextView对象,您可以移动.旋转.缩放.透明度设置其文本,当然,如果它有一个背景图像,背景图像会随着文本变化. 补间动画通过XML或Android代码定义,建议使用XML文件定义,因为它更具可读性.可重用性. 2> Drawable动画其实就是Frame动画(帧动画),它允许你实现像播放幻灯片一样的效果,这种动画的实质其实是Dra

Android动画效果——1.帧动画2.补间动画3.跳转画面(三)

Android--动画效果1.帧动画2.补间动画3.跳转画面 插值器类 xml属性值 说明 LinearInterpolator @android:anim/linear_interpolatorr 动画以均匀的速度改变. AccelerateInterpolator @android:anim/accelerate_interpolator 在动画开始时改变速度较慢,然后开始加速. AccelerateDecelerateInterpolator @android:anim/accelerat