由類的關係圖發現原來ViewFlipper是ViewAnimator的子類,而ViewAnimator又是FrameLayout的子類。看到這個繼承關係是否對ViewFlipper的工作原理有一定的猜想? 其實ViewFlipper工作機制很簡單,如上圖,就是將添加到ViewFlipper中的子Vi ...
平時我們在使用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是這樣的簡單?