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

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

 

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

public class MarqueeTextView extends TextView implements Runnable 
{
    public enum MarqueeDirection 
    {
        LEFT, RIGHT
    } 
    private volatile boolean  m_bIsStop = false;
    private int      m_iTextWidth = 0;// 文字寬度
    private boolean  m_bIsMeasure = false;
    private int      m_iDistance = 1;      
    private int      m_iSpeed = 25;      
    private int      m_iScrollPosition = 0;
    private MarqueeDirection m_Direction = MarqueeDirection.RIGHT;

   public MarqueeTextView(Context context)
   {
       super(context);
       setEllipsize(TruncateAt.MARQUEE);
       setSingleLine(true);
       onResume();
   }

   @Override
   protected void onDraw(Canvas canvas)
   {
       if (!m_bIsMeasure)
       { // 文字寬度只要獲取一次就好啦!
              getTextWidth();
              startScroolFrom0();
              m_bIsMeasure = true;
       }
      super.onDraw(canvas); // 先設定好再畫,才不會有殘影
   }

   public void onResume()
   {
      startScroll();
   }

   public void onPause()
   {
      stopScroll();
   }

   private void getTextWidth()
   {
      Paint paint = getPaint();
      String str = getText().toString();
      m_iTextWidth = (int) paint.measureText(str);
   }

   protected void startScroolFrom0()
   { // 跑馬燈初始值方向
      if (m_Direction == MarqueeDirection.RIGHT)
         m_iScrollPosition = -getWidth();
      else
         m_iScrollPosition = m_iTextWidth;

      scrollTo(m_iScrollPosition, 0);
   }

   @Override
   public void run()
   {
      if (m_bIsStop)
         return;

      // 跑馬燈初始值方向
      if (m_Direction == MarqueeDirection.RIGHT)
         m_iScrollPosition += m_iDistance;
      else
         m_iScrollPosition -= m_iDistance;
      scrollTo(m_iScrollPosition,0);
      if ((m_Direction == MarqueeDirection.RIGHT && getScrollX() >= m_iTextWidth) || // 由右向左捲
         (m_Direction == MarqueeDirection.LEFT &&  getScrollX() <= -getWidth())) // 由左向右捲
      {
         startScroolFrom0();
      }
      postDelayed(this, m_iSpeed);
   }

   private void startScroll()
   {
      m_bIsStop = false;
      removeCallbacks(this);
      post(this);
   }

   private void stopScroll()
   {
      m_bIsStop = true;
      removeCallbacks(this);
   }
}
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments