Android 自定義跑馬燈 實現超長文字,滾動完當前在繼續切換下一條
阿新 • • 發佈:2018-11-17
1 前言
最近專案上有一個跑馬燈的需求。
需求:
- 無限滾動,可以自動切換下一條
- 如果當前的文字超過一屏,則滾動完當前再切換下一條
第一點很簡單,但是第二點就比較蛋疼了,看了網上很多輪子都沒有太合適的,於是自己寫了一個。 記錄總結一下Android 跑馬燈的實現方式,和我自定義跑馬燈的思路。
原始碼已託管到Github:https://github.com/ieewbbwe/MarqueeView
先看下最後得效果圖吧:
2 內容
2.1 需求實現
2.1.1 使用RecycleView + 自定義跑馬燈
思路: 1. 利用橫向RecycleView實現排列 2. smoothScroll實現滑動 3. 內嵌跑馬燈實現標題超長的滾動
2.1.4 ViewFlipper + 自定義跑馬燈
這個實現方式是好基友告訴我的,很nice了,原理也是巢狀。
因為使用了ViwFilpper 因此想要改變滑動方向很簡單。直用該進入\退出動畫即可
思路:
1. 外層使用ViewFlipper切分View並且滾動
2. 內層使用自定義跑馬燈滾動
2.1.3 自定義控制元件,Draw() 出滾動效果
思路
1. draw出前後兩筆文字
2. 利用view的重繪,不斷更新文字位置實現滾動
2.2 跑馬燈的實現方式
2.2.1 TextView 設定Marquee
<TextView
android:id ="@+id/marqueeNormal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ellipsize="marquee"
android:focusable="true"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:text="我是普通的TextView跑馬燈~跑啊跑~!" />
灰常簡單,主要是這幾個熟悉:
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
但是!!有些時候會無效!因為跑馬燈要跑起來需要獲取到焦點,但是由於介面複雜,有時候焦點你好控制!TextView宣告只有再isFocus的時候才會走跑馬燈,具體的原始碼自己去看了。
那麼這種情況的終極解決方案是!直接繼承TextView,並Override isFocused(),永久返回True。就可以了,但是還會有彈出Dialog,螢幕不亮等時候會出現問題。
最終解決如下,實測可用:
public class MarqueeText3 extends AppCompatTextView {
public MarqueeText3(Context context) {
this(context,null);
}
public MarqueeText3(Context context, AttributeSet attrs) {
super(context, attrs);
//設定單行
setSingleLine();
//設定Ellipsize
setEllipsize(TextUtils.TruncateAt.MARQUEE);
//獲取焦點
setFocusable(true);
//走馬燈的重複次數,-1代表無限重複
setMarqueeRepeatLimit(1);
//強制獲得焦點
setFocusableInTouchMode(true);
}
@Override
public boolean isFocused() {
return true;
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if (focused) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
if (hasWindowFocus)
super.onWindowFocusChanged(hasWindowFocus);
}
}
2.2.2 自定義控制元件-使用ViewFlipper
2.2.3 自定義控制元件-使用Scroller 滾動
2.2.4 自定義控制元件-使用ScrollTo()
2.2.5 自定義控制元件-Canvas Draw()
3 總結
總的來說,就兩種思路:
- 外層滾動巢狀內層滾動
- 繪製當前和下一個,滾動
使用手感:
使用自定義Draw的方式 可控性高,靈活,但是容易出錯,計算方式比較麻煩,例子中寫的還不完善;
使用巢狀的方式簡單,快速,可控性不高,比如滾動時的停頓時間。
點選事件
還有一個需要注意的是,draw方法的時候,因為沒有控制好點選的問題,必須再切換的時候做到迅速,不然會有一個錯誤情況:當第一條未滾動出螢幕,但第二條一家滑入一部分的時候,點選會出現錯誤,不清楚當前是屬於第一條還是第二條。
參考: