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);
	}
}


国际惯例

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

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

简洁   稳定   优雅   无限可能!


  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Android 中实现 TextView 文字滚动可以使用以下两种方式: 一、使用 Marquee(跑马灯)属性 在布局文件中的 TextView 中添加以下属性: ``` <TextView android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="这是一段需要滚动的文字这是一段需要滚动的文字这是一段需要滚动的文字" android:singleLine="true" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:marqueeRepeatLimit="marquee_forever" android:scrollHorizontally="true" android:padding="5dp" android:textColor="#000000" android:textSize="20sp" /> ``` 其中,关键属性为: - android:ellipsize="marquee":当文字超出 TextView 的宽度时,显示省略号并开启跑马灯效果。 - android:focusable="true" 和 android:focusableInTouchMode="true":设置为可获得焦点,让 TextView 能够滚动。 - android:marqueeRepeatLimit="marquee_forever":设置跑马灯无限循环。 - android:scrollHorizontally="true":可水平滚动。 在 Java 代码中,调用 setHorizontallyScrolling() 方法也可以实现水平滚动,示例代码如下: ``` TextView textView = findViewById(R.id.text_view); textView.setHorizontallyScrolling(true); ``` 二、使用代码实现 在 Java 代码中使用 TextView 的 setEllipsize() 方法和 setMarqueeRepeatLimit() 方法可以实现 TextView文字滚动效果。示例代码如下: ``` TextView textView = findViewById(R.id.text_view); textView.setText("这是一段需要滚动的文字这是一段需要滚动的文字这是一段需要滚动的文字"); textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.MARQUEE); textView.setMarqueeRepeatLimit(-1); textView.setFocusable(true); textView.setFocusableInTouchMode(true); textView.requestFocus(); ``` 需要注意的是,如果在代码中设置了跑马灯效果,还需要在布局文件中设置以下属性: ``` android:singleLine="true" android:scrollHorizontally="true" ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值