Android 上下滾動(跑馬燈)效果實現
阿新 • • 發佈:2018-12-21
產品的有個需求是 文字上下滾動,第一想到的是用屬性動畫實現,2個TextView 切換滾動,網上看了一堆資料大部分都是 TextSwitch,寫部落格不貼效果圖真的是很惆悵,不知道具體效果如何,第一次進入切換是否有問題,還有就是最後一個切換到第二個是否有問題,動畫是否流暢等,啥都看不到。所以還是按照第一個想法,找到了類似的做法,但是好像有點問題,於是修改一番,效果圖如下:(gif幀率有點低,不是很順暢,真機上挺好的)
思路就是2個TextView 利用屬性動畫上下切換,延遲傳送執行緒觸發下次滾動。
程式碼如下:
1.ScrrollTextView.java
import android.animation.ObjectAnimator; import android.content.Context; import android.os.Handler; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import com.lanjinger.choiassociatedpress.R; import java.util.List; /** * 上下滾動的 textView */ public class ScrollTextView extends LinearLayout { private TextView mBannerTV1; private TextView mBannerTV2; private Handler handler; private boolean isShow = false; private int startY1, endY1, startY2, endY2; private Runnable runnable; private List<String> list; private int position = 0; private int offsetY = 100; private boolean hasPostRunnable = false; public ScrollTextView(Context context) { this(context, null); } public ScrollTextView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public ScrollTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); View view = LayoutInflater.from(context).inflate(R.layout.widget_scroll_text_layout, this); mBannerTV1 = view.findViewById(R.id.tv_banner1); mBannerTV2 = view.findViewById(R.id.tv_banner2); handler = new Handler(); runnable = new Runnable() { @Override public void run() { isShow = !isShow; if (position == list.size() - 1) { position = 0; } if (isShow) { mBannerTV1.setText(list.get(position++)); mBannerTV2.setText(list.get(position)); } else { mBannerTV2.setText(list.get(position++)); mBannerTV1.setText(list.get(position)); } startY1 = isShow ? 0 : offsetY; endY1 = isShow ? -offsetY : 0; ObjectAnimator.ofFloat(mBannerTV1, "translationY", startY1, endY1).setDuration(300).start(); startY2 = isShow ? offsetY : 0; endY2 = isShow ? 0 : -offsetY; ObjectAnimator.ofFloat(mBannerTV2, "translationY", startY2, endY2).setDuration(300).start(); handler.postDelayed(runnable, 3000); } }; } public List<String> getList() { return list; } public void setList(List<String> list) { this.list = list; //處理最後一條資料切換到第一條資料 太快的問題 if (list.size() > 1) { list.add(list.get(0)); } } public void startScroll() { mBannerTV1.setText(list.get(0)); if (list.size() > 1) { if(!hasPostRunnable) { hasPostRunnable = true; //處理第一次進入 第一條資料切換第二條 太快的問題 handler.postDelayed(runnable,3000); } } else { //只有一條資料不進行滾動 hasPostRunnable = false; // mBannerTV1.setText(list.get(0)); } } public void stopScroll() { handler.removeCallbacks(runnable); hasPostRunnable = false; } }
注意點:1.就是開啟和關閉滾動,都需要在控制元件外面控制。如果需要在控制元件內部自行控制也可以,
onAttachedToWindow 這裡開啟執行緒,注意判斷列表是否為空。
2.當列表資料大於1條是,我會手動在後面再加上第一條資料,為了避免,最後一條切換到一條是滾動太快(即動效不明顯的問題),我這裡沒有判空,因為傳遞過來是一定有資料的,為了嚴瑾可以加上判空.
2.widget_scroll_text_layout.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tv_banner1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:ellipsize="end" android:singleLine="true" android:textColor="@color/skin_common_title" android:textSize="12sp" /> <TextView android:id="@+id/tv_banner2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:ellipsize="end" android:singleLine="true" android:textColor="@color/skin_common_title" android:textSize="12sp" /> </RelativeLayout>
3.具體呼叫
ScrollTextView marqueeText = headView.findViewById(R.id.xxxx); List<String> demographicsList = new ArrayList<>(); demographicsList.add("今日測試股票 上市"); demographicsList.add("今日科倫藥業 中國人保 可申購"); demographicsList.add("今日中國平安 上市"); marqueeText.setList(demographicsList); marqueeText.startScroll();
注意:正確處理生命週期的問題,什麼時候呼叫starScroll(),什麼時候呼叫stopScroll(),根據具體的生命週期而定;
尾:
感覺這樣寫想要啥動效都可以自行定義,更具需求定製屬性動畫就好了,也不需要多餘的new TextView();簡單的看了下,好像TextSwitch 要麻煩點。
今日任務做完,研究 TextSwitch 去,對比下2者的優缺點;