Android最实用TextView文字逐个打出效果

对于文字逐个打出效果,我们一下子想到的做法可能都是弄一个for循环,不断更改文本内容。

这法子表面看起来可以,但实际实用起来问题多多,比如对于多行居中对齐的文本,打出效果就不是渐进出来,因为受到对齐和换行的影响,随着文字增多,文本布局会不断变化。

下面看最实用和稳定的文字逐个打出效果自定义组件FadeInTextView。

1、FadeInTextView完全继承TextView的所有特性,没有任何负面影响,使用FadeInTextView就像使用TextView一样;

2、简单设置出效果:

(1)setFadeInDuration:设置打出效果总共时长;

(2)setMoveUnitLength:设置渐进步长为几个字符,默认为1;

(3)setFadeInMaskColor:设置遮罩颜色,即未显示文字区域的颜色。



完整源码如下:

import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.text.Layout;
import android.util.AttributeSet;
import android.widget.TextView;

public class FadeInTextView extends TextView {
	private static final int DEFAULT_UNIT_LENGTH = 2;
	private static final int DEFAULT_DURATION = 3820;
	private List<Rect> lineRects = new ArrayList<Rect>();
	private int duration = DEFAULT_DURATION;
	private int moveUnitLength;
	private int fromLine = 0;
	private int moveCount;
	private int fromStart;
	private int maskColor;
	private Paint paint;
	private FadeInListener fadeInListener;

	private volatile boolean fadeInFinished = false;

	private boolean hasCallListener = false;

	public FadeInTextView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public FadeInTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public FadeInTextView(Context context) {
		super(context);
	}

	public boolean isFadeInFinished() {
		return fadeInFinished;
	}

	public void setFadeInDuration(int duration) {
		this.duration = duration;
	}

	public int getFadeInDuration() {
		return duration;
	}

	public void setMoveUnitLength(int moveUnitLength) {
		this.moveUnitLength = moveUnitLength;
	}

	public void setFadeInMaskColor(int maskColor) {
		this.maskColor = maskColor;
	}

	public void setFadeInListener(FadeInListener fadeInListener) {
		this.fadeInListener = fadeInListener;
	}

	public void activateFadeInListener() {
		this.hasCallListener = false;
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (lineRects.isEmpty()) {
			getLineRects();
			if (fadeInListener != null && !hasCallListener) {
				fadeInListener.onFadeInStart(this);
			}
		}
		if (paint == null) {
			paint = new Paint();
			paint.setColor(maskColor);
			paint.setAntiAlias(true);
			paint.setStyle(Style.FILL);
		}
		for (int i = fromLine; i < lineRects.size(); i++) {
			Rect rect = new Rect(lineRects.get(i));
			if (i == fromLine) {
				rect.left = fromStart;
			}
			canvas.drawRect(rect, paint);
		}

		if (!computeNextFrame()) {
			fadeInFinished = true;
			if (fadeInListener != null && !hasCallListener) {
				fadeInListener.onFadeInEnd(this);
				hasCallListener = true;
			}
			return;
		}
		postDelayed(new Runnable() {
			@Override
			public void run() {
				invalidate();
			}
		}, duration / moveCount);
	}

	private boolean computeNextFrame() {
		if (lineRects.size() <= fromLine) {
			return false;
		}
		Rect currentLineRect = lineRects.get(fromLine);
		if (fromStart >= currentLineRect.right) {
			return false;
		}
		fromStart = fromStart + moveUnitLength;
		if (fromStart >= currentLineRect.right) {
			fromLine++;
			if (lineRects.size() > fromLine) {
				fromStart = lineRects.get(fromLine).left;
			} else {
				fromStart = 0;
			}
		}
		return true;

	}

	private void getLineRects() {
		Layout layout = getLayout();
		if (layout == null) {
			return;
		}
		int lineCount = layout.getLineCount();
		int totalLength = 0;
		for (int i = 0; i < lineCount; i++) {
			Rect rect = new Rect();
			rect.left = (int) layout.getLineLeft(i);
			rect.right = (int) layout.getLineRight(i);
			rect.top = layout.getLineTop(i);
			rect.bottom = layout.getLineBottom(i);
			if (i == 0) {
				fromStart = rect.left;
			}
			lineRects.add(rect);
			totalLength = totalLength + rect.width();
		}
		if (moveUnitLength <= 0) {
			moveUnitLength = DEFAULT_UNIT_LENGTH;
		}
		moveCount = totalLength / moveUnitLength;
		if (moveCount <= 0) {
			moveCount = 1;
		}
	}

	public static interface FadeInListener {
		public void onFadeInStart(TextView tv);

		public void onFadeInEnd(TextView tv);
	}
}


国际惯例

————————————————————————————————————————————————————————

作者:薄荷记账  (转载请注明原作者)

简洁   稳定   优雅   无限可能!


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值