前言
Android 的 TextView
虽然有属性 android:ellipsize="marquee"
有文字滚动效果,但是坑多,比如焦点变化了就不动了,而且不能控制滚动的速度,在RecyclerView
里的表现更是灾难级的。为了解决以上问题,所以就有了MarqueeTextView
:一个由 Kotlin 实现的文本滚动自定义 View。MarqueeTextView: Kotlin 实现文本横向滚动,跑马灯效果。 (gitee.com)
相关属性
xml 属性
属性 | 说明 |
---|---|
android:textSize | 文字大小 |
android:textColor | 文字颜色 |
android:text | 文本内容 |
marqueeRepeat | 循环模式:singe -单次执行;singleLoop -单项循环;fillLoop -填充循环 |
marqueeItemDistance | 每个item之间的距离, marqueeRepeat=fillLoop 有效 |
marqueeStartLocationDistance | 开始的起始位置 按距离控件左边的百分比 0~1之间 |
marqueeSpeed | 文字滚动速度 |
marqueeResetLocation | 重新改变内容的时候 , 是否初始化 位置,默认为true,改变 |
主要方法
-
start
: 滚动开始 -
stop
: 滚动停止 -
toggle
: 切换滚动开始/停止
使用方式
<com.xin.marquee.text.view.MarqueeTextView
android:id="@+id/tv1"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="16dp"
android:text="Kotlin 实现文本横向滚动,跑马灯效果。"
android:textSize="14dp"
app:marqueeRepeat="fillLoop"
app:marqueeSpeed="5" />
代码里调用start
方法
具体实现
让文字滚动起来其实就是定时在短时间内把文来,这样看着就会有连续滚动的感觉。
下面仅说明实现效果的核心方法,源码自取:MarqueeTextView: Kotlin 实现文本横向滚动,跑马灯效果。 (gitee.com)
- 核心类:
android.text.TextPaint
和android.os.handler
- 获取绘制文本的宽度
private fun getTextWidth(text: String?): Float {
if (text.isNullOrEmpty()) {
return 0f
}
return textPaint.measureText(text)
}
- 填充循环模式下的文本拼接
if (repeat == REPEAT_FILL_LOOP) {
mFinalDrawText = ""
//计算文本的宽度
mSingleContentWidth = getTextWidth(targetContent)
if (mSingleContentWidth > 0) {
// 最大可见内容项数
val maxVisibleCount = ceil(width / mSingleContentWidth.toDouble()).toInt() + 1
repeat(maxVisibleCount) {
mFinalDrawText += targetContent
}
}
contentWidth = getTextWidth(mFinalDrawText)
}
- 绘制文本内容
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// 忽略部分代码 ...
// 绘制文本
if (mFinalDrawText.isNotBlank()) {
canvas.drawText(mFinalDrawText, xLocation, height / 2 + textHeight / 2, textPaint)
}
}
- 定时绘制内容——滚起来
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
if (msg.what == WHAT_RUN) {
mRef.get()?.apply {
if (speed > 0) {
xLocation -= speed
invalidate()
// 50 毫秒绘制一次
sendEmptyMessageDelayed(WHAT_RUN, 50)
}
}
}
}
总结
整个实现下来总的来说还是比较简单的,能够满足平时文本滚动(跑马灯)效果的需求了。代码量很少的,也比较清晰,大家看下源码应该就清楚了。有不清楚的欢迎交流。