Android 开发之轻量级文本动画

版权声明:本文为博主原创文章,未经博主允许不得转载。欢迎访问http://github.com/shenhuanet 转载请注明出处: https://blog.csdn.net/klxh2009/article/details/70052561

Android 开发之轻量级文本动画

转载请注明出处 传送门 本文出自【付小华的博客】

引言

在掘金上看到推文,用JS实现了文字动画和数字动画 animate text,效果如下:
图片

文本动画, 几行代码页面效果瞬间就提升了

自己就在Android端简单粗暴地模仿了一个,具体实现就是handler,random,效果如下:
图片

使用

<xxxxxxxx.widget.AnimateText
    android:id="@+id/animationText1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="50dp"
    android:lines="10"
    android:text="\u3000\u3000寄居在桂子山叔叔家中,不觉已是两个多月了,居室的环境极为情幽静谧,古朴自然之中又透着一种雅致。特别是那满山的木樨,中秋一过,便黄灿灿地开满枝头,悠悠的香气随风飘送。昨夜,西风渐紧,刮得楼下梧桐树“沙沙”地响,躺在床上,心想,明晨,又该是花落知多少了!今早推门一看,湿湿的水泥小径上,满是枯枝败叶,再细看枝叶间,黄灿灿的一片,竟是桂花!不由得脱口而出一句诗来:昨夜西风过园林,吹落黄花满地金!不禁心头一动,眼前幻化出父亲的影子来。"
    android:textColor="@color/colorPrimary"
    android:textSize="16sp" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:onClick="animation1"
    android:text="重新播放" />

<xxxxxxxx.widget.AnimateText
    android:id="@+id/animationText2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="50dp"
    android:text="666666.66"
    android:textColor="@color/colorPrimary"
    android:textSize="25sp"
    app:changeCount="50"
    app:isNumber="true" />

    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:onClick="animation2"
    android:text="重新播放" />

代码

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatTextView;
import android.util.AttributeSet;

import com.shenhua.newscachedemo.R;

import java.util.Random;

/**
 * Created by shenhua on 4/11/2017.
 * Email [email protected]
 */
public class AnimateText extends AppCompatTextView {

    private Handler handler = new Handler(Looper.getMainLooper());
    private boolean annimaStart = false; // 开始时是否展示动画
    private boolean isNumber = false; // 是否渲染为数字动画
    private int time = 20;// 动画时长
    private int changeCount = 32; // 数字动画数字变化次数
    private int startNumber = 0; // 渲染为数字动画时 动画的开始数字
    private int endNumber = 0; // 渲染为数字动画时 动画的结束数字
    private OnAnimationEndListener listener;// 动画结束时的监听
    private String text;// 文本

    public AnimateText(Context context) {
        this(context, null);
    }

    public AnimateText(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AnimateText(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        if (attrs != null) {
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AnimateText);
            annimaStart = a.getBoolean(R.styleable.AnimateText_annimaStart, false);
            isNumber = a.getBoolean(R.styleable.AnimateText_isNumber, false);
            time = a.getInteger(R.styleable.AnimateText_time, 20);
            changeCount = a.getInteger(R.styleable.AnimateText_changeCount, 32);
            a.recycle();
        }
        text = getText().toString();
        if (isNumber) {
            startNumber = text.length() - 1;
            endNumber = (int) Float.parseFloat(text);
        }
        if (annimaStart) {
            startAnimate();
        }
    }

    public void startAnimate() {
        this.startAnimate(null);
    }

    public void startAnimate(final OnAnimationEndListener listener) {
        this.listener = listener;
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (isNumber) {
                    showNumAnimate();
                } else {
                    showNormalAnimate();
                }
            }
        }).start();
    }

    private void showNormalAnimate() {
        char[] cs = text.toCharArray();
        final StringBuffer buffer = new StringBuffer();
        for (char c : cs) {
            buffer.append(c);
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.post(new Runnable() {
                @Override
                public void run() {
                    AnimateText.this.setText(buffer.toString(), BufferType.NORMAL);
                }
            });
        }
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (listener != null) {
                    listener.onEnd();
                }
            }
        });
    }

    private void showNumAnimate() {
        for (int i = 0; i < changeCount; i++) {
            final float t = nextFloat();
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.post(new Runnable() {
                @Override
                public void run() {
                    setText(String.valueOf(t), BufferType.NORMAL);
                }
            });
        }
        handler.post(new Runnable() {
            @Override
            public void run() {
                setText(text, BufferType.NORMAL);
            }
        });
    }

    private float nextFloat() {
        return startNumber + ((endNumber - startNumber) * new Random().nextFloat());
    }

    public int getTime() {
        return time;
    }

    public void setTime(int time) {
        this.time = time;
    }

    public boolean isAnnimaStart() {
        return annimaStart;
    }

    public void setAnnimaStart(boolean annimaStart) {
        this.annimaStart = annimaStart;
    }

    public boolean isNumber() {
        return isNumber;
    }

    public void setNumber(boolean number) {
        isNumber = number;
    }

    public int getStartNumber() {
        return startNumber;
    }

    public void setStartNumber(int startNumber) {
        this.startNumber = startNumber;
    }

    public int getChangeCount() {
        return changeCount;
    }

    public void setChangeCount(int changeCount) {
        this.changeCount = changeCount;
    }

    public void setText(String text) {
        this.text = text;
        setText(text, BufferType.NORMAL);
    }

    public OnAnimationEndListener getListener() {
        return listener;
    }

    public void setListener(OnAnimationEndListener listener) {
        this.listener = listener;
    }

    public interface OnAnimationEndListener {
        void onEnd();
    }
}
  • attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="AnimateText">
        <attr name="time" format="integer" />
        <attr name="annimaStart" format="boolean" />
        <attr name="isNumber" format="boolean" />
        <attr name="changeCount" format="integer" />
    </declare-styleable>
</resources>
  • 可使用的方法
    setter 方法均可在外部调用,代码中已有详细说明。

好了,就这么多。

猜你喜欢

转载自blog.csdn.net/klxh2009/article/details/70052561