最早在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;
}
};
}

布局文件和主文件非常easy:

<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的更多相关文章

  1. Android 自带图标库 android.R.drawable

    在xml文件中调用. android:title="@string/secure_connect"android:orderInCategory="100"an ...

  2. 浅谈Android系统的图标设计规范

    http://homepage.yesky.com/89/11620089.shtml 目前移动平台的竞争日益激烈,友好的用户界面可以帮助提高用户体验满意度,图标Icon是用户界面中一个重要的组成部分 ...

  3. android动效开篇

    大神博客:http://blog.csdn.net/tianjian4592/article/details/44155147 在现在的Android App开发中,动效越来越受到产品和设计师同学的重 ...

  4. 一个使用openGL渲染的炫丽Android动画库二(碎片化曲面动画)

    续一个使用openGL渲染的炫丽Android动画库 MagicSurfaceView v1.1.0发布, 新增碎片化曲面动画 地址:https://github.com/gplibs/android ...

  5. Android重绘ListView高度

    Android重绘ListView高度 经常会有这样需求,需要ListView默认将所有的条目显示出来,这就需要外层使用ScrollView,ScrollView里面放置一个重绘高度的ListView ...

  6. Android中为图标加上数字

    Android中为图标加上数字--用于未读短信数提醒,待更新应用数提醒等 http://flysnow.iteye.com/blog/906770

  7. 解决Eclipse中Android SDK Manager图标不见了的问题

    在Eclipse中安装完ADT后,发现 Android SDK Manager图标不见了,Android Virtual Device Manager图标也不见了. 解决这个问题,可用如下方法: 打开 ...

  8. 【腾讯bugly干货分享】Android自绘动画实现与优化实战——以Tencent OS录音机波形动

    前言 本文为腾讯bugly的原创内容,非经过本文作者同意禁止转载,原文地址为:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1180 ...

  9. Android手绘效果实现

    效果图 原理 大概介绍一下实现原理.首先你得有一张图(废话~),接下来就是把这张图的轮廓提取出来,轮廓提取算法有很多,本人不是搞图像处理的,对图像处理感兴趣的童鞋可以查看相关资料.如果你有好的轮廓提取 ...

随机推荐

  1. Spring Tool Suite(简称STS)针对SimpleDateFormat.pase函数的实参值不做检验,异常直接默认值之

    Spring Tool Suite(简称STS)是 Spring 团队开发的一款基于Eclipse的IDE,旨在简化开发Spring MVC 应用的流程.可以自动生成spring相关的配置文件.比如a ...

  2. axure制作圆形组件——axure制作技巧

    Axure本身是没有直接提供圆形组件的,所以很多朋友在微博上问,如何使用axure制作圆形,难道都要找美工-- Axure没有提供圆形组件,但是它提供了一个万能组件--矩形组件,只要有矩形组件,我们就 ...

  3. linux下C/C++IDE比较——Code::Blocks

    工欲善其事,必先利其器.用了这么久的linux,现在比较主流的几个C/C++的IDE基本已都用过了,现在来对他们做一下简单的比较. 1.VIM首先要说的是VIM.我认为,VIM只是一个编辑器,不能算是 ...

  4. 1.1.7-学习Opencv与MFC混合编程之---为画图工具添加工具栏

    源代码:http://download.csdn.net/detail/nuptboyzhb/3961701 哎,其实里面有很多图片的,本来看起开很明了的,资源连接里有详细的文档,比下面的看的舒服的多 ...

  5. python - Django: Converting an entire set of a Model's objects into a single dictionary - Stack Overflow

    python - Django: Converting an entire set of a Model's objects into a single dictionary - Stack Over ...

  6. 大容量XFS异常处理

    今天在检查报警的时候发现部分数据异常,登陆备份机查看文件状态的时候发现磁盘空间已经满了,inode也已经有问题了,因此先停掉了所有的备份进程,开始检查问题. 首先是磁盘空间满了,尝试删除部分文件,发现 ...

  7. VS2010(2012)中使用Unit Testing进行单元测试

    原文 VS2010(2012)中使用Unit Testing进行单元测试 使用VS 2012自带的Unit Testing工具进行单元测试是非常方便的.网上关于这方面的例子很多,这篇随笔只起个人学习笔 ...

  8. eclipse发布项目报错:Multiple Contexts hava a path of “/xxx“

    你的位置:首页 > Java编程 > eclipse发布项目报错:Multiple Contexts hava a path of “/xxx“ eclipse发布项目报错:Multipl ...

  9. PLSQL数据导入

    导入数据 (1)      首先以管理员身份登录plsql; (2)      新建命令窗口 (3)      创建用户,设置帐号,密码 创建语句:create user usernameidenti ...

  10. Android:自定义滚动边缘(EdgeEffect)效果

    Android可滚动控件(GridView.ListView.ScrollView等)当用户滚动到头的时候会有个边缘反馈效果,在4.0上默认为Holo蓝色效果.  如果您的App自定义了主题颜色,比如 ...