Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android不一樣的走馬燈,MarqueeManualView

Android不一樣的走馬燈,MarqueeManualView

編輯:關於Android編程

眾所周知,當需要文字進入走馬燈狀態的時候,需要設置屬性

 

android:ellipsize="marquee"

 

但是有時候並不能啟動走馬燈效果,這是因為失去了焦點導致的,這時候可以通過強制設置焦點,從而促使不會不啟動走馬燈,同時如果沒有啟動走馬燈,設置setSelected(true)也會開啟走馬燈效果,

當然我們也可以重寫Textview強制開啟走馬燈。

以下是我自定義的一個強制開啟走馬燈的TextView , MarqueeFocusedTextView

 

package com.bluewindtalker.weight;

/**
 * 
 */

import android.content.Context;
import android.graphics.Rect;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;

/**
 * @author bluewindtalker
 * @description 防止由於焦點問題而不能自動啟動的走馬燈textview,這裡建議加上以下屬性。
 *      android:singleLine="true"
 *       android:focusableInTouchMode="true"
        android:ellipsize="marquee"
        android:marqueeRepeatLimit="marquee_forever"
        android:focusable="true"
        
        代碼效果相同。(另:正常的textview如果沒有自動啟動,可以通過設置setSelected(true)開啟走馬燈)
        如需要高級使用,請查看MarqueeManualView
 * @data Jun 22, 2016 -- 2:56:11 PM
 * @reference http://m15031966454.blog.163.com/blog/static/201261060201222043240815/
 */
public class MarqueeFocusedTextView extends TextView {
  
  /**
   * @param context
   */
  public MarqueeFocusedTextView(Context context) {
    this(context, null);
  }

  /**
   * @param context
   * @param attrs
   */
  public MarqueeFocusedTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initMarquee();
  }
  
  /**
   * @param context
   * @param attrs
   * @param defStyleAttr
   */
  public MarqueeFocusedTextView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initMarquee();
  }
  
  @Override
  public boolean isFocused() {
    //跑馬燈, 只有當焦點在它上面時才有效。
    return true;
  }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        // 關於MarqueeText類中為什麼要復寫onFocusChanged()方法,那是因為如果不寫,在Textview 獲得焦點後,再失
        //去焦點時 字就會停止“跑”了,所以如果想讓它一直跑下去就復寫onFocusChanged(),並且裡面什麼也不做(主要是不能調用父類的方法)
        //http://m15031966454.blog.163.com/blog/static/201261060201222043240815/
//    super.onFocusChanged(focused, direction, previouslyFocusedRect);
    }


    /**
     * 初始化,設置必要的屬性
     */
    private void initMarquee(){
        setFocusable(true);
        setSingleLine();
        setFocusableInTouchMode(true);
        setEllipsize(TextUtils.TruncateAt.MARQUEE);
        setMarqueeRepeatLimit(-1);
    }
}

但是這種原生的TextView衍生出的走馬燈存在以下問題

 

無法設置走馬燈文字之間間隔;

無法設置走馬燈速度;

無法設置走馬燈啟動、關閉時機;

 

無法設置走馬燈暫停的時間長短;

 

這些都是在TextView中設置好的,例如間距以下是TextView源碼

 

void start(int repeatLimit) {
            if (repeatLimit == 0) {
                stop();
                return;
            }
            mRepeatLimit = repeatLimit;
            final TextView textView = mView.get();
            if (textView != null && textView.mLayout != null) {
                mStatus = MARQUEE_STARTING;
                mScroll = 0.0f;
                final int textWidth = textView.getWidth() - textView.getCompoundPaddingLeft() -
                        textView.getCompoundPaddingRight();
                final float lineWidth = textView.mLayout.getLineWidth(0);
                final float gap = textWidth / 3.0f;//這裡將間距設固定了,沒法通過反射等方式更改
                mGhostStart = lineWidth - textWidth + gap;
                mMaxScroll = mGhostStart + textWidth;
                mGhostOffset = lineWidth + gap;
                mFadeStop = lineWidth + textWidth / 6.0f;
                mMaxFadeScroll = mGhostStart + lineWidth + lineWidth;

                textView.invalidate();
                mChoreographer.postFrameCallback(mStartCallback);
            }
        }
另外走馬燈的啟動時間、間隔時間、速度都是固定的,有興趣的童鞋可以去查看下TextView源碼

 

 

	private static final int MARQUEE_DELAY = 1200;
        private static final int MARQUEE_RESTART_DELAY = 1200;
        private static final int MARQUEE_DP_PER_SECOND = 30;

 

 

如果簡單的認為復制粘貼TextView源碼重新再寫一份TextView即可,那就大錯特錯了,因為TextView引用了隱藏的類,無法獲取對應的類。這時候就需要我們重新寫一個自定義的走馬燈控件,來實現以上功能。

這個控件名字是MarqueeManualView

主要思想就是通過一個FrameLayout循環調用兩個內容一樣的TextView實現循環調用。

 

這個mMoveTextOut是當前展示的TextView從屏幕顯示的區域移動到看不見的區域

 

	mMoveTextOut = new TranslateAnimation(0, -mTextDifference, 0, 0);
        mMoveTextOut.setDuration(marqueeDuration);
        mMoveTextOut.setInterpolator(mInterpolator);
        mMoveTextOut.setFillAfter(true);

        mMoveTextOut.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                if (isStop) {
                    return;
                }
                postDelayed(mMarqueeRunnable, mPauseTime);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

 

這個mMoveTextIn是TextView從屏幕外,移動到屏幕中view的起點的動畫

 

       mMoveTextIn = new TranslateAnimation(mTextDifference, 0, 0, 0);
        mMoveTextIn.setDuration(marqueeDuration);
        mMoveTextIn.setInterpolator(mInterpolator);
        mMoveTextIn.setFillAfter(true);


 

通過以上兩個TextView走的動畫進行循環,

\

具體步驟:

1.mTextView使用動畫mMoveTextOut,而mGhostTextView使用動畫mMoveTextIn,

2.當mGhostTextView到達mTextView初始位置的時候,則停頓下,交替兩個控件的動畫,mGHostTextView使用動畫mMoveTextOut,而mTextView使用動畫mMoveTextIn.

重復上面1,2.

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved