最早在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. perl eval函数

    29.2.32 eval • eval BLOCK • eval EXPR • eval eval 关键字在Perl 里起两种不同的但相关的作用.这些目的是用两种形式的语法 来表现的, eval BL ...

  2. 北风风hadoop课程体系

    课程一.基于Linux操作系统平台下的Java语言开发(20课时)课程简介本套课程主要介绍了Linux系统下的Java环境搭建及最基础的Java语法知识.学习Linux操作系统下Java语言开发的好处 ...

  3. boost::asio async_write也不能保证一次发完所有数据 一

    你要是看过basic_stream_socket的文档,里面提到async_write_some不能保证将所有要发送的数据都发出去.并且提到如果想这样做,需要使用boost asio的async_wr ...

  4. QT使用scrollarea显示图片,完美解决方案

    需求: 在界面上点击“显示图片”按钮,会调用scrollarea窗口显示图片,窗口大小能根据图片大小自动调整,但是最大为1024*768,图片过大就要有滚动条来显示 IDE环境: QT Creator ...

  5. Swift - 使用下划线(_)来分隔数值中的数字

    为了增强较大数值的可读性,Swift语言增加了下划线(_)来分隔数值中的数字. 不管是整数,还是浮点数,都可以使用下划线来分隔数字. 1 2 3 4 //数值可读性 let value1 = 10_0 ...

  6. static作用

    C程序一直由下列部分组成:      1)正文段——CPU运行的机器指令部分:一个程序仅仅有一个副本:仅仅读,防止程序因为意外事故而改动自身指令:      2)初始化数据段(数据段)——在程序中全部 ...

  7. C++学习之路—运算符重载(二)运算符重载作为类的成员函数和友元函数

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 对运算符重载的函数有两种处理方式:(1)把运算符 ...

  8. 手动配置S2SH三大框架报错(二)

    十二月 08, 2013 9:34:39 下午 org.apache.catalina.core.AprLifecycleListener init 严重: An incompatible versi ...

  9. VC/MFC 在ListCtl 控件中随鼠标移动提示单元格信息

    BEGIN_MESSAGE_MAP(CTipListCtrl, CListCtrl) //{{AFX_MSG_MAP(CTipListCtrl) ON_WM_MOUSEMOVE() ON_WM_DES ...

  10. RobotFrameWork(十一)AutoItLibrary测试库在win7(64bit)下安装及简单使用

    最近安装AutoItLibrary,发现在win7 x64下无法安装成功,后来经过定位,发现是3rdPartyTools\AutoIt目录下面AutoItX3.dll的问题.因为AutoItX3.dl ...