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;
}
};
}
布局文件和主文件非常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的更多相关文章
- Android 自带图标库 android.R.drawable
在xml文件中调用. android:title="@string/secure_connect"android:orderInCategory="100"an ...
- 浅谈Android系统的图标设计规范
http://homepage.yesky.com/89/11620089.shtml 目前移动平台的竞争日益激烈,友好的用户界面可以帮助提高用户体验满意度,图标Icon是用户界面中一个重要的组成部分 ...
- android动效开篇
大神博客:http://blog.csdn.net/tianjian4592/article/details/44155147 在现在的Android App开发中,动效越来越受到产品和设计师同学的重 ...
- 一个使用openGL渲染的炫丽Android动画库二(碎片化曲面动画)
续一个使用openGL渲染的炫丽Android动画库 MagicSurfaceView v1.1.0发布, 新增碎片化曲面动画 地址:https://github.com/gplibs/android ...
- Android重绘ListView高度
Android重绘ListView高度 经常会有这样需求,需要ListView默认将所有的条目显示出来,这就需要外层使用ScrollView,ScrollView里面放置一个重绘高度的ListView ...
- Android中为图标加上数字
Android中为图标加上数字--用于未读短信数提醒,待更新应用数提醒等 http://flysnow.iteye.com/blog/906770
- 解决Eclipse中Android SDK Manager图标不见了的问题
在Eclipse中安装完ADT后,发现 Android SDK Manager图标不见了,Android Virtual Device Manager图标也不见了. 解决这个问题,可用如下方法: 打开 ...
- 【腾讯bugly干货分享】Android自绘动画实现与优化实战——以Tencent OS录音机波形动
前言 本文为腾讯bugly的原创内容,非经过本文作者同意禁止转载,原文地址为:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1180 ...
- Android手绘效果实现
效果图 原理 大概介绍一下实现原理.首先你得有一张图(废话~),接下来就是把这张图的轮廓提取出来,轮廓提取算法有很多,本人不是搞图像处理的,对图像处理感兴趣的童鞋可以查看相关资料.如果你有好的轮廓提取 ...
随机推荐
- asp.net2.0安全性(4)--Login系列控件--转载来自车老师
前面主要说了与安全相关的一系列的类,现在我们使用这些类就可以做出我们自己的安全系统了.其实微软的目的远不至于此,下面我们就来看一下微软为我们提供的Login系列控件. Login系列控件是微软为了简化 ...
- chrome你这是入侵OSX了么?
今天突然发现安装chrome的应用后,会在Dock中出现如下图标,点击即可启动chrome相关应用,很是方便.
- jdbcType与javaType的对应关系
java.sql.Types 值 Java 类型 IBM DB2 Oracle Sybase SQL Informix IBM Content Manager BIGINT java.lang.lon ...
- Linux下的链接文件
整理自<鸟哥的Linux私房菜>,整理者:华科小涛http://www.cnblogs.com/hust-ghtao/ Linux中的链接文件分为两种:硬链接和软链接.软链接(symbol ...
- <转载>如何解决子级用float浮动父级div高度不能自适应的问题
转载:http://www.kwstu.com/ArticleView/divcss_2013101582430202 解决子级对象使用css float浮动 而父级div不能自适应高度,不能被父级内 ...
- 通过崩溃地址找错误行数之Delphi版
通过崩溃地址找错误行数之Delphi版2009-5-11 17:42:35 来源: 转载 作者:网络 访问:360 次 被顶:2 次 字号:[大 中 小]核心提示:什么是 MAP 文件?简单地讲, M ...
- Boost Thread学习笔记五
多线程编程中还有一个重要的概念:Thread Local Store(TLS,线程局部存储),在boost中,TLS也被称作TSS,Thread Specific Storage.boost::thr ...
- hdu 4714 Tree2cycle dp
用树形dp做的,dp[t][i]表示t及其孩子入度都已经小于等于2并且t这个节点的入度等于i的最优解. 那么转移什么的自己想想就能明白了. 关键在于这个题目会暴栈,所以我用了一次bfs搜索出节点的顺序 ...
- 积累的VC编程小技巧之列表框
1.列表框中标题栏(Column)的添加 创建一个List Control,其ID为IDC_LIST,在其Styles属性项下的View项里选择Report.Align项里选择Top.Sort项里选择 ...
- regsvr32 命令小集注册OCX控件,注册控件(包括十几个举例)
Regsvr32 进程文件: regsvr32 or regsvr32.exe 进程名称: Microsoft DLL Registration Service 英文描述: regsvr32.ex ...