Android - TextView动画加载文字

一、前言

        项目中有需求想让开屏Actvity 的Textview加载的时候有个从左到右的动画,其实很多地方也会用到。

二、实现

        首先肯定是TextView去实现,去自定义View

        原理就是利用StringBuffer 去append Text,然后不断刷新。一下就是实现代码

第一步:继承AppCompatTextView,

public class AnimateText extends AppCompatTextView {

    private Handler handler = new Handler(Looper.getMainLooper());
    private boolean annimaStart = false; // 开始时是否展示动画
    private boolean isNumber = false; // 是否渲染为数字动画
    private int time = 100;// 动画时长
    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, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AnimateText(Context context, 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, 100);
            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();
    }
}

二、xml中使用

<com.xxx.xxx.w.AnimateText
        android:id="@+id/tv_app_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="66dp"
        android:gravity="center"
        android:lines="1"
        android:text="GENERAL"
        android:textColor="@color/black"
        android:textSize="20sp"
        android:visibility="visible" />

三、java代码中使用,获取实例后startAnimate

mAnimateText.startAnimate();

四、atter.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>

就这些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值