依然是github开源项目:WaitingDots

这个项目代码不多,实现的非常easy。可是非常有意思由于动画的基本元素不是画出来的,而是使用了spannableString来实现。

  • DotsTextView.java
  • JumpingSpan.java
  • MainActivity.java

    DotstextView是动画的实现主体。

    JumpingSpan是基本元素,是动画中的插件

    MainActivity中仅仅要在布局中引入DotsTextView就可以。

    下面是切割线,show code:
package pl.tajchert.sample;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.text.style.ReplacementSpan;
/* ReplacementSpan真是一个挺奇妙的东西。在官方api上介绍甚少
*几个主要功能函数也是do nothing.
* 本例中自己定义的translationX,translationY没有发挥作用。假设给两个变量赋值
* 那么第一个JumpingSpan距离前面元素距离增大,这里这样使用是为了让每一个"."为一个单独的单元进行独立操作
*/
public class JumpingSpan extends ReplacementSpan { private float translationX = 0;
private float translationY = 0; @Override
public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fontMetricsInt) {
return (int) paint.measureText(text, start, end);
} @Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
canvas.drawText(text, start, end, x + translationX, y + translationY, paint);
} public void setTranslationX(float translationX) {
this.translationX = translationX;
} public void setTranslationY(float translationY) {
this.translationY = translationY;
}
}
package pl.tajchert.sample;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Looper;
import android.text.SpannableString;
import android.text.Spanned;
import android.util.AttributeSet;
import android.widget.TextView; import pl.tajchert.waitingdots.R; public class DotsTextView extends TextView { private JumpingSpan dotOne;
private JumpingSpan dotTwo;
private JumpingSpan dotThree; private int showSpeed = 700; private int jumpHeight;
private boolean autoPlay;
private boolean isPlaying;
private boolean isHide;
private int period;
private long startTime; private boolean lockDotOne;
private boolean lockDotTwo;
private boolean lockDotThree; private Handler handler;
private AnimatorSet mAnimatorSet = new AnimatorSet();
private float textWidth; public DotsTextView(Context context) {
super(context);
init(context, null);
} public DotsTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
} public DotsTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
} private void init(Context context, AttributeSet attrs) {
handler = new Handler(Looper.getMainLooper());
//自己定义属性
if (attrs != null) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WaitingDots);
period = typedArray.getInt(R.styleable.WaitingDots_period, 6000);
jumpHeight = typedArray.getInt(R.styleable.WaitingDots_jumpHeight, (int) (getTextSize() / 4));
autoPlay = typedArray.getBoolean(R.styleable.WaitingDots_autoplay, true);
typedArray.recycle();
}
dotOne = new JumpingSpan();
dotTwo = new JumpingSpan();
dotThree = new JumpingSpan();
//将每一个点设置为jumpingSpan类型
SpannableString spannable = new SpannableString("...");
spannable.setSpan(dotOne, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(dotTwo, 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(dotThree, 2, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
setText(spannable, BufferType.SPANNABLE); textWidth = getPaint().measureText(".", 0, 1);
//一下两个是把updateListener加到点1上,通过它来进行刷新动作
ObjectAnimator dotOneJumpAnimator = createDotJumpAnimator(dotOne, 0);
dotOneJumpAnimator.addUpdateListener(new AnimatorUpdateListener() { @Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
invalidate();
}
});
//这里通过animationSet来控制三个点的组合动作
mAnimatorSet.playTogether(dotOneJumpAnimator, createDotJumpAnimator(dotTwo,
period / 6), createDotJumpAnimator(dotThree, period * 2 / 6)); isPlaying = autoPlay;
if(autoPlay) {
start();
}
} public void start() {
isPlaying = true;
//一旦開始就INFINITE
setAllAnimationsRepeatCount(ValueAnimator.INFINITE);
mAnimatorSet.start();
}
/*动画的实现核心
*@param jumpingSpan 传入点。
* @delay 动画执行延迟,通过这个參数让三个点进行有时差的运动
*/
private ObjectAnimator createDotJumpAnimator(JumpingSpan jumpingSpan, long delay) {
ObjectAnimator jumpAnimator = ObjectAnimator.ofFloat(jumpingSpan, "translationY", 0, -jumpHeight);
/*setEvaluator这个重要。功能是为了通过方程来平滑的实现点运动的“节奏感”,能够试试把这段去掉。
你会发现点会以默认的速度上下运动,特别生硬。TypeEvaluator中的evaluate能够计算出点的当前位置。
通过对当前点的计算间接设计了点的轨迹运动,和时间插值TimeInterpolator达到同样的效果。就好比你不知道速度可是你知道每秒所在的位置相当于速度了。 这个计算方法是这种:能够參见这个博文
http://blog.csdn.net/serapme/article/details/47006049
ValueAnimator还封装了一个TypeAnimator。依据開始、结束值与TimeIniterpolator计算得到的值计算出属性值。
ValueAnimator依据动画已进行的时间跟动画总时间(duration)的比计算出一个时间因子(0~1),然后依据TimeInterpolator计算出还有一个因子,最后TypeAnimator通过这个因子计算出属性值,如上例中10ms时:
首先计算出时间因子,即经过的时间百分比:t=10ms/40ms=0.25
经插值计算(inteplator)后的插值因子:大约为0.15。上述样例中用了AccelerateDecelerateInterpolator,计算公式为(input即为时间因子):
(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
最后依据TypeEvaluator计算出在10ms时的属性值:0.15*(40-0)=6pixel。上例中TypeEvaluator为FloatEvaluator,计算方法为 :
public Float evaluate(float fraction, Number startValue, Number endValue) {
float startFloat = startValue.floatValue();
return startFloat + fraction * (endValue.floatValue() - startFloat);
}
*/
jumpAnimator.setEvaluator(new TypeEvaluator<Number>() { @Override
public Number evaluate(float fraction, Number from, Number to) {
return Math.max(0, Math.sin(fraction * Math.PI * 2)) * (to.floatValue() - from.floatValue());
}
});
jumpAnimator.setDuration(period);
jumpAnimator.setStartDelay(delay);
jumpAnimator.setRepeatCount(ValueAnimator.INFINITE);
jumpAnimator.setRepeatMode(ValueAnimator.RESTART);
return jumpAnimator;
}
//下面部分非核心功能也没难度就不凝视了~主要是由于懒~
public void stop() {
isPlaying = false;
setAllAnimationsRepeatCount(0);
} private void setAllAnimationsRepeatCount(int repeatCount) {
for (Animator animator : mAnimatorSet.getChildAnimations()) {
if (animator instanceof ObjectAnimator) {
((ObjectAnimator) animator).setRepeatCount(repeatCount);
}
}
} public void hide() { createDotHideAnimator(dotThree, 2).start(); ObjectAnimator dotTwoMoveRightToLeft = createDotHideAnimator(dotTwo, 1);
dotTwoMoveRightToLeft.addUpdateListener(new AnimatorUpdateListener() { @Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
invalidate();
}
}); dotTwoMoveRightToLeft.start();
isHide = true;
} public void show() {
ObjectAnimator dotThreeMoveRightToLeft = createDotShowAnimator(dotThree, 2); dotThreeMoveRightToLeft.start(); ObjectAnimator dotTwoMoveRightToLeft = createDotShowAnimator(dotTwo, 1);
dotTwoMoveRightToLeft.addUpdateListener(new AnimatorUpdateListener() { @Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
invalidate();
}
}); dotTwoMoveRightToLeft.start();
isHide = false;
} private ObjectAnimator createDotHideAnimator(JumpingSpan span, float widthMultiplier) {
return createDotHorizontalAnimator(span, 0, -textWidth * widthMultiplier);
} private ObjectAnimator createDotShowAnimator(JumpingSpan span, int widthMultiplier) {
return createDotHorizontalAnimator(span, -textWidth * widthMultiplier, 0);
} private ObjectAnimator createDotHorizontalAnimator(JumpingSpan span, float from, float to) {
ObjectAnimator dotThreeMoveRightToLeft = ObjectAnimator.ofFloat(span, "translationX", from, to);
dotThreeMoveRightToLeft.setDuration(showSpeed);
return dotThreeMoveRightToLeft;
} public void showAndPlay() {
show();
start();
} public void hideAndStop() {
hide();
stop();
} public boolean isHide() {
return isHide;
} public boolean isPlaying() {
return isPlaying;
} public void setJumpHeight(int jumpHeight) {
this.jumpHeight = jumpHeight;
} public void setPeriod(int period) {
this.period = period;
}
}

毫无疑问在activity中引入布局中就可以。

dotsTextView = (DotsTextView) findViewById(R.id.dots);

一个简单使用的loadingview。

使用SpannableString实现一个load小动画的更多相关文章

  1. 用css3做一个求婚小动画

    概述 本案例主要是运用到了css3的animation.keyframes.transform等属性,熟悉了,就可以做更多的其他动画效果,这几个属性功能非常强大. 详细 代码下载:http://www ...

  2. 利用@keyframe及animation做一个页面Loading时的小动画

    前言 利用@keyframe规则和animation常用属性做一个页面Loading时的小动画. 1  @keyframe规则简介 @keyframes定义关键帧,即动画每一帧执行什么. 要使用关键帧 ...

  3. 微信小程序循环列表点击每一个单独添加动画

    首先,咱们看一下微信小程序动画怎么实现,我首先想到的是anime.js,但是引入之后用不了,微信小程序内的css也无法做到循环的动态,我就去找官方文档看看有没有相应的方法,哎,还真有 点击这里查看 微 ...

  4. CSS3-实现单选框radio的小动画

    在微信上看到一个教程文,觉得制作的小动画还是很有意思的,自己也试验了一下.一开始动画怎么都不执行(我用的HB),因为内置浏览器对css3的不兼容.加上各种浏览器前缀后就好了.但是旋转那个效果,在HB里 ...

  5. WPF之小动画一

    定义动画: 直接使用Element进行BeginAnimation DoubleAnimation animation = new DoubleAnimation(); animation.By = ...

  6. 如何制作网页小动画?——gif or png

    一.场景与动画 为了拉动网站氛围,或者吸引用户浏览焦点,需要使用一些小动画.这种动画不是(gif)单纯的重复,而是需要需要一些控制和交互,比如在动画完成后打开一个对话框.动画有几个基本要素(时间控制, ...

  7. 一个Hibernate小程序

    基本步骤 在前一篇博文Hibernate环境搭建中为大家详细的介绍如何搭建一个学习新类库的学习环境.今天,为大家带来一个Hibernate小例子,让大家能够快速上手. 步骤如下: 1.配置hibern ...

  8. 利用jQuery实现用户名片小动画

    我爱撸码,撸码使我感到快乐!大家好,我是Counter.下面给大家介绍利用jQuery实现的小动画,非常的简便,如果有原生js操作的话,那么就不止这么多行了.至于CSS,个人觉得,这边CSS布局也蛮重 ...

  9. 前端动画小记---bilibili ( ゜-゜)つロ客户下载小动画

    逛哔哩哔哩 ( ゜-゜)つロPC版的时候看到一个蛮有意思的动画,指导用户去下载客户端,于是摸索实现了一个. 原动画效果 可以看到,一个静止的小电视人,当鼠标移动到电视人身上时,电视人慢慢变身成为一个小 ...

随机推荐

  1. bzoj3225 [Sdoi2008]立方体覆盖——扫描线

    3225: [Sdoi2008]立方体覆盖 Description A君近日为准备省队选拔,特意进行了数据结构的专项训练.训练过程中就遇到了“矩形面积并”这道经典问题,即:给出N个各边与坐标轴平行(垂 ...

  2. #421 Div1 C

    #421 Div1 C 题意 在 (0, n) 和 (m, 0) 处各有一个装置,从起始点(0, 0)出发,首先走短路到 (m, 0) 拿起装置回到起始点,再去 (0, n) 处拿起装置回到起始点.当 ...

  3. 树链剖分【p3178】[HAOI2015]树上操作

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点 ...

  4. jcl sort comp3 to 表示型

    Lets say your packed data is at 10th column and is of length 6, S9(4)V99 You could try the following ...

  5. lua的模式匹配

    模式: 字符类:(character classes) . all characters %a letters %c control characters %d digits %l lower -ca ...

  6. Java 使用IE浏览器下载文件,文件名乱码问题

    使用Servlet实现文件下载功能时,使用IE下载出现文件名乱码; 网上常见的解决办法是通过"user-agen"来判断浏览器: if (req.getHeader("u ...

  7. jquery的attr和prop区别之实例

    对于HTML元素本身就带有的固有属性,在处理时,使用prop方法. 对于HTML元素我们自己自定义的DOM属性,在处理时,使用attr方法. html文件 <tr> <th>& ...

  8. 超级惊艳 10款HTML5动画特效推荐[转]

    ylbtech_html5_demo 今天我们要来推荐 10 款超级惊艳的 HTML5 动画特效,有一些是基于 CSS3 和 jQuery 的,比较实用,特别是前几个 HTML5 动画,简直酷毙了,现 ...

  9. Spring整合Hibernate的时候使用hibernate.cfg.xml

    Spring整合Hibernate其实也就是把Hibernate的SessionFactory对象封装成:org.springframework.orm.hibernate3.LocalSession ...

  10. 通过JBoss反序列化(CVE-2017-12149)浅谈Java反序列化漏洞

    前段时间学校学习J2EE,用到了jboss,顺便看了下jboss的反序列化,再浅谈下反序列化漏洞. Java序列化,简而言之就是把java对象转化为字节序列的过程.而反序列话则是再把字节序列恢复为ja ...