textview - 跑马灯

textview 的跑马灯不用说了吧,大家肯定都知道这是个啥,但是呢我还是放个图吧:


232041141272978.gif

实现单个跑马灯


跑马灯的核心是这2个 xml 设置

        android:ellipsize="marquee"
        android:singleLine="true"

一定要用 singleLine 而不要用 lines

ellipsize 表示的是当 - 文字长度超过textview宽度时的显示方式,有几个配置:

  • start:表示将文字开头省略,用“…”代替
  • middle:表示将文字中间省略,用“…”代替
  • end:表示将文字末尾省略,用“…”代替
  • marquee:表示当文字一行展示不下时,以跑马灯滚动效果展示
  • none:即默认,没有任何效果

若是这么简单的话我也没必要特意开篇幅来写这个啦,主要是因为蛋疼的我们配置完着2个 xml 属性后不管用...

这里面很多前人就去翻 textview 源码了,发现 textview 里面维护了文字宽度,若是 文字宽度 超过 textview 宽度就会进行相应处理,比如 ellipsize 属性设置为 marquee 跑马灯模式后就会进行滚动显示,看源码就是 canvas 的 translate 位移操作,操作画布

    if (mMarquee != null && mMarquee.isRunning()) {
        final float dx = -mMarquee.getScroll();
        canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
    }

蛋疼的是还没完,textview 必须在获取焦点时才能就行canvas 的 translate 位移操作,所以我们还需要加上下面3个参数,获取焦点和跑马灯重复模式

        android:focusable="true"
        android:focusableInTouchMode="true"
        android:marqueeRepeatLimit="marquee_forever""

好啦,这样 textview 就能跑马式的跑起来啦

实现多个跑马灯


然后蛋疼的又来啦,一个页面要是游多个跑马灯的 textview 就只能有一个起作用,就是我们配置了上面全部的 5 个 xml 属性都没用,因为系统默认同时只有一个 textview 能获取焦点

那怎么办,我翻了翻,经过前辈们不停的探寻,发现我们只要更改 textview 返回焦点值方法,返回值一直给 true 就行啦,所以我们得自定义一个 textview 啦,很简单的啦~

class MarqueeTextView : TextView {

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)

    // 重写这里即可
    override fun isFocused(): Boolean {
        return true
    }

}
232057302214909.gif

这样就搞定啦,不难哦,大家快掌握~

你可能感兴趣的:(textview - 跑马灯)