[Android 開發] 如何在利用 TextView 做左右滾動的文字跑馬燈?

一般我們做跑馬燈,都是使用 WebView 來實做,但是 WebView 的效能並不好,而其實 TextView 就有內建跑馬燈的功能了,但不好控制,所以還是自己寫程式碼來控制是最好的,接下來就讓我們看一下怎麼做吧!

 

而這篇文章是參考「自定义TextView跑马灯效果,可控制启动,停止,和速度(含源码)」一文改的,主要是原文在特定的情況下會有殘影產生,所以海芋加以改寫,程式碼如下:

  1. public class MarqueeTextView extends TextView implements Runnable 
  2. {
  3.     public enum MarqueeDirection 
  4.     {
  5.         LEFT, RIGHT
  6.     } 
  7.     private volatile boolean  m_bIsStop = false;
  8.     private int      m_iTextWidth = 0;// 文字寬度
  9.     private boolean  m_bIsMeasure = false;
  10.     private int      m_iDistance = 1;      
  11.     private int      m_iSpeed = 25;      
  12.     private int      m_iScrollPosition = 0;
  13.     private MarqueeDirection m_Direction = MarqueeDirection.RIGHT;
  14.  
  15.    public MarqueeTextView(Context context)
  16.    {
  17.        super(context);
  18.        setEllipsize(TruncateAt.MARQUEE);
  19.        setSingleLine(true);
  20.        onResume();
  21.    }
  22.  
  23.    @Override
  24.    protected void onDraw(Canvas canvas)
  25.    {
  26.        if (!m_bIsMeasure)
  27.        { // 文字寬度只要獲取一次就好啦!
  28.               getTextWidth();
  29.               startScroolFrom0();
  30.               m_bIsMeasure = true;
  31.        }
  32.       super.onDraw(canvas); // 先設定好再畫,才不會有殘影
  33.    }
  34.  
  35.    public void onResume()
  36.    {
  37.       startScroll();
  38.    }
  39.  
  40.    public void onPause()
  41.    {
  42.       stopScroll();
  43.    }
  44.  
  45.    private void getTextWidth()
  46.    {
  47.       Paint paint = getPaint();
  48.       String str = getText().toString();
  49.       m_iTextWidth = (int) paint.measureText(str);
  50.    }
  51.  
  52.    protected void startScroolFrom0()
  53.    { // 跑馬燈初始值方向
  54.       if (m_Direction == MarqueeDirection.RIGHT)
  55.          m_iScrollPosition = -getWidth();
  56.       else
  57.          m_iScrollPosition = m_iTextWidth;
  58.  
  59.       scrollTo(m_iScrollPosition, 0);
  60.    }
  61.  
  62.    @Override
  63.    public void run()
  64.    {
  65.       if (m_bIsStop)
  66.          return;
  67.  
  68.       // 跑馬燈初始值方向
  69.       if (m_Direction == MarqueeDirection.RIGHT)
  70.          m_iScrollPosition += m_iDistance;
  71.       else
  72.          m_iScrollPosition -= m_iDistance;
  73.       scrollTo(m_iScrollPosition,0);
  74.       if ((m_Direction == MarqueeDirection.RIGHT && getScrollX() >= m_iTextWidth) || // 由右向左捲
  75.          (m_Direction == MarqueeDirection.LEFT &&  getScrollX() <= -getWidth())) // 由左向右捲
  76.       {
  77.          startScroolFrom0();
  78.       }
  79.       postDelayed(this, m_iSpeed);
  80.    }
  81.  
  82.    private void startScroll()
  83.    {
  84.       m_bIsStop = false;
  85.       removeCallbacks(this);
  86.       post(this);
  87.    }
  88.  
  89.    private void stopScroll()
  90.    {
  91.       m_bIsStop = true;
  92.       removeCallbacks(this);
  93.    }
  94. }