我们平时使用TextView往往让它作为一个显示文字的容器,但TextView的功能并不局限于此。在未来的几天里,我将会记录一些TextView的一些高级应用。
今天就来聊聊淡入淡出的效果。淡入淡出的文字显示效果,其实很多地方都用到过,比如我们常去的新闻网站,里面忽闪忽闪的文字,就是这种,许多朋友刚看到这个的时候会想,不就是淡入淡出嘛,Android的动画里面早就有了。然而你要是这么想,我只能说:搜羊搜森剖。
因为不知道插入视频,所以就不上视频了。我直接贴代码吧。
public class MutableForegroundColorSpan extends CharacterStyle implements
UpdateAppearance {
public static final String TAG = "MutableForegroundColorSpan";
private int mColor;
@Override
public void updateDrawState(TextPaint tp) {
tp.setColor(mColor);
}
public int getColor() {
return mColor;
}
public void setColor(int color) {
this.mColor = color;
}
}
这是一个实体类,用于储存文字的颜色以及更新动画状态。紧接着,我把主要的部分也贴上去,具体是怎么实现的,我最后再解释。
public class MarqueeText extends TextView {
private String mTextString;
private SpannableString mSpannableString;
private double[] mAlphas;
private MutableForegroundColorSpan[] mSpans;
private boolean mIsVisible;
private boolean mIsTextResetting = false;
private int mDuration = 2500;
ValueAnimator animator;
ValueAnimator.AnimatorUpdateListener listener = new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
Float percent = (Float)valueAnimator.getAnimatedValue();
resetSpannableString(mIsVisible ? percent : 2.0f - percent);
}
};
public MarqueeText(Context context) {
super(context);
init();
}
public MarqueeText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
this.mIsVisible = false;
animator = ValueAnimator.ofFloat(0.0f, 2.0f);
animator.addUpdateListener(listener);
animator.setDuration(mDuration);
}
public void toggle(){
if (mIsVisible) {
hide();
} else {
show();
}
}
public void show(){
mIsVisible = true;
animator.start();
}
public void hide(){
mIsVisible = false;
animator.start();
}
public void setIsVisible(boolean isVisible){
mIsVisible = isVisible;
resetSpannableString(isVisible == true ? 2.0f : 0.0f);
}
public boolean getIsVisible(){
return mIsVisible;
}
private void resetSpannableString(double percent){
mIsTextResetting = true;
int color = getCurrentTextColor();
for (int i = 0; i < this.mTextString.length(); i++) {
MutableForegroundColorSpan span = mSpans[i];
span.setColor(Color.argb(clamp(mAlphas[i] + percent), Color.red(color), Color.green(color), Color.blue(color)));
}
setText(mSpannableString);
mIsTextResetting = false;
}
private void resetAlphas(int length){
mAlphas = new double[length];
for(int i=0; i < mAlphas.length; i++){
mAlphas[i] = Math.random()-1;
}
}
private void resetIfNeeded(){
if (!mIsTextResetting){
mTextString = getText().toString();
mSpannableString = new SpannableString(this.mTextString);
mSpans = new MutableForegroundColorSpan[this.mTextString.length()];
for (int i = 0; i < this.mTextString.length(); i++) {
MutableForegroundColorSpan span = new MutableForegroundColorSpan();
mSpannableString.setSpan(span, i, i+1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mSpans[i] = span;
}
resetAlphas(mTextString.length());
resetSpannableString(mIsVisible ? 2.0f : 0);
}
}
public void setText(String text) {
super.setText(text);
resetIfNeeded();
}
@Override
public void setText(CharSequence text, TextView.BufferType type) {
super.setText(text, type);
resetIfNeeded();
}
private int clamp(double f){
return (int)(255*Math.min(Math.max(f, 0), 1));
}
public void setDuration(int duration){
this.mDuration = duration;
animator.setDuration(duration);
}
}
我们看到代码,这是一个自定义的TextView,另外,我们这里插入一个知识点:ValueAnimator,属性动画的一部分,关于属性动画,我准备在下几篇文章里面进行详细介绍。
ValueAnimator是属性动画的核心部分,它本身不提供任何动画效果,而更像是数值发生器,用来产生具有一定规律的数字,从而让调用者来控制动画的实现过程。它一般性用法如下:
ValueAnimator animator;
ValueAnimator.AnimatorUpdateListener listener = new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
Float percent = (Float) valueAnimator.getAnimatedValue();
resetSpannableString(mIsVisible ? percent : 2.0f - percent);
}
};
通常情况下,ValueAnimator 的AnimatorUpdateListener中监听数值的变换,从而完成动画的交换。
截止目前,java代码的部分也就差不多了。就像其他的Textview拓展的使用一样,我们直接把自己的TextView全称放在XML布局文件里面。开始动画方法就是调用它的start()方法,好了,以上就是关于textview淡入淡出效果的全部实现过程了。