一、前言
项目中有需求想让开屏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>
就这些。