1. 程式人生 > >了解ViewFlipper工作機制

了解ViewFlipper工作機制

splay sdn ted runnable sent first per erp asf

平時我們在使用ViewFlipper的時候一方面感嘆ViewFlipper的使用很簡單,另一方面,我們時常感嘆ViewFlipper給我們的接口方法太少,很多常用的效果都不好做,很難施展拳腳,這篇文章將詳
細介紹ViewFlipper的架構以及它的工作原理,相信看了這篇文章後你會發現ViewFlipper能展現的效果也可以很多,自己也可以根據自己的需求來定制屬於自己的ViewFlipper。
類的繼承關系圖:

技術分享圖片

由類的關系圖發現原來ViewFlipper是ViewAnimator的子類,而ViewAnimator又是FrameLayout的子類。看到這個繼承關系是否對ViewFlipper的工作原理有一定的猜想?

技術分享圖片

其實ViewFlipper工作機制很簡單,如上圖,就是將添加到ViewFlipper中的子View按照順序定時的顯示是其中一個子View,其他的子View設置為Gone狀態。下面我們通過源碼來詳細解讀這一過程。

ViewFlipper中的主要方法:

@android.view.RemotableViewMethod
public void setFlipInterval(int milliseconds) {
    mFlipInterval = milliseconds;
}

/**
* Start a timer to cycle through child views
*/
public
void startFlipping() { mStarted = true; updateRunning(); } /** * No more flips */ public void stopFlipping() { mStarted = false; updateRunning(); }

private void updateRunning(boolean flipNow) {
    boolean running = mVisible && mStarted && mUserPresent;
    if (running != mRunning) {
        
if (running) { showOnly(mWhichChild, flipNow); postDelayed(mFlipRunnable, mFlipInterval); } else { removeCallbacks(mFlipRunnable); } mRunning = running; } if (LOGD) { Log.d(TAG, "updateRunning() mVisible=" + mVisible + ", mStarted=" + mStarted + ", mUserPresent=" + mUserPresent + ", mRunning=" + mRunning); } }

看這三個方法,我們就能知道不管是startFlipper還是stopFlipper方法,他們都是調用了updateRunning方法,不同的只是他們對於mStart這個變量設置的值不同,mStart值也就決定了ViewFlipper是start還是stop。

updateRunning方法它主要就是根據running值來判斷是發送消息到消息棧中,還是移除消息。

private final Runnable mFlipRunnable = new Runnable() {
    @Override
    public void run() {
        if (mRunning) {
            showNext();
            postDelayed(mFlipRunnable, mFlipInterval);
        }
    }
};

如果是startFlipper,,也就是將下一個View的狀態設置為Visible,其他的View設置為Gone狀態。執行這一工作的方法為showNext()。此方法的實現在ViewAnimator。其實在ViewFlipper中,也就幹了這麽點事情。下面我們來看ViewAnimator。

ViewAnimator中的主要方法:

public void showNext() {  
       setDisplayedChild(mWhichChild + 1);  
   }  

public void setDisplayedChild(int whichChild) {  
       mWhichChild = whichChild;  
       if (whichChild >= getChildCount()) {  
           mWhichChild = 0;  
       } else if (whichChild < 0) {  
           mWhichChild = getChildCount() - 1;  
       }  
       boolean hasFocus = getFocusedChild() != null;  
       // This will clear old focus if we had it  
       showOnly(mWhichChild);  
       if (hasFocus) {  
           // Try to retake focus if we had it  
           requestFocus(FOCUS_FORWARD);  
       }  
   }  

這兩個方法也就是計算出下一個View該顯示哪個,確定了具體要顯示的View後,就會調用showOnly(mWhichChild)方法

void showOnly(int childIndex) {  
        final int count = getChildCount();  
        for (int i = 0; i < count; i++) {  
            final View child = getChildAt(i);  
            final boolean checkForFirst = (!mFirstTime || mAnimateFirstTime);  
            if (i == childIndex) {  
                if (checkForFirst && mInAnimation != null) {  
                    child.startAnimation(mInAnimation);  
                }  
                child.setVisibility(View.VISIBLE);  
                mFirstTime = false;  
            } else {  
                if (checkForFirst && mOutAnimation != null && child.getVisibility() == View.VISIBLE) {  
                    child.startAnimation(mOutAnimation);  
                } else if (child.getAnimation() == mInAnimation)  
                    child.clearAnimation();  
                child.setVisibility(View.GONE);  
            }  
        }  
    }  

這個方法主要的工作就是顯示mWhichChild,將其他的設置為Gone狀態。同時在這個方法中還會進行切換動畫的調用,如果有動畫的話。

其實在ViewAnimator類中,主要就是幹了兩件事,一件就是按照要求將需要顯示的子view設置為Visible狀態,其他的子View設置為Gone狀態。另外一件就是動畫的處理工作。

看完這個有沒有發現其實ViewFlipper是這樣的簡單?

了解ViewFlipper工作機制