textview 的跑馬燈不用說(shuō)了吧退子,大家肯定都知道這是個(gè)啥整慎,但是呢我還是放個(gè)圖吧:
實(shí)現(xiàn)單個(gè)跑馬燈
跑馬燈的核心是這2個(gè) xml 設(shè)置
android:ellipsize="marquee"
android:singleLine="true"
一定要用 singleLine 而不要用 lines
ellipsize 表示的是當(dāng) - 文字長(zhǎng)度超過(guò)textview寬度時(shí)的顯示方式棋蚌,有幾個(gè)配置:
- start:表示將文字開(kāi)頭省略丧蘸,用“…”代替
- middle:表示將文字中間省略,用“…”代替
- end:表示將文字末尾省略每界,用“…”代替
- marquee:表示當(dāng)文字一行展示不下時(shí)日缨,以跑馬燈滾動(dòng)效果展示
- none:即默認(rèn)钱反,沒(méi)有任何效果
若是這么簡(jiǎn)單的話(huà)我也沒(méi)必要特意開(kāi)篇幅來(lái)寫(xiě)這個(gè)啦,主要是因?yàn)榈疤鄣奈覀兣渲猛曛?個(gè) xml 屬性后不管用...
這里面很多前人就去翻 textview 源碼了匣距,發(fā)現(xiàn) textview 里面維護(hù)了文字寬度面哥,若是 文字寬度 超過(guò) textview 寬度就會(huì)進(jìn)行相應(yīng)處理,比如 ellipsize 屬性設(shè)置為 marquee 跑馬燈模式后就會(huì)進(jìn)行滾動(dòng)顯示毅待,看源碼就是 canvas 的 translate 位移操作幢竹,操作畫(huà)布
if (mMarquee != null && mMarquee.isRunning()) {
final float dx = -mMarquee.getScroll();
canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
}
蛋疼的是還沒(méi)完,textview 必須在獲取焦點(diǎn)時(shí)才能就行canvas 的 translate 位移操作恩静,所以我們還需要加上下面3個(gè)參數(shù),獲取焦點(diǎn)和跑馬燈重復(fù)模式
android:focusable="true"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever""
好啦蹲坷,這樣 textview 就能跑馬式的跑起來(lái)啦
實(shí)現(xiàn)多個(gè)跑馬燈
然后蛋疼的又來(lái)啦驶乾,一個(gè)頁(yè)面要是游多個(gè)跑馬燈的 textview 就只能有一個(gè)起作用,就是我們配置了上面全部的 5 個(gè) xml 屬性都沒(méi)用循签,因?yàn)橄到y(tǒng)默認(rèn)同時(shí)只有一個(gè) textview 能獲取焦點(diǎn)
那怎么辦级乐,我翻了翻,經(jīng)過(guò)前輩們不停的探尋县匠,發(fā)現(xiàn)我們只要更改 textview 返回焦點(diǎn)值方法风科,返回值一直給 true 就行啦撒轮,所以我們得自定義一個(gè) textview 啦,很簡(jiǎn)單的啦~
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)
// 重寫(xiě)這里即可
override fun isFocused(): Boolean {
return true
}
}
這樣就搞定啦贼穆,不難哦题山,大家快掌握~