查看: 2124|回复: 0

[Android教程] 了解ViewFlipper工作机制

发表于 2018-2-20 08:00:03
  1. 平时我们在使用ViewFlipper的时候一方面感叹ViewFlipper的使用很简单,另一方面,我们时常感叹ViewFlipper给我们的接口方法太少,很多常用的效果都不好做,很难施展拳脚,这篇文章将详<br>细介绍ViewFlipper的架构以及它的工作原理,相信看了这篇文章后你会发现ViewFlipper能展现的效果也可以很多,自己也可以根据自己的需求来定制属于自己的ViewFlipper。
复制代码
  1. 类的继承关系图:
复制代码

由类的关系图发现原来ViewFlipper是ViewAnimator的子类,而ViewAnimator又是FrameLayout的子类。看到这个继承关系是否对ViewFlipper的工作原理有一定的猜想?

其实ViewFlipper工作机制很简单,如上图,就是将添加到ViewFlipper中的子View按照顺序定时的显示是其中一个子View,其他的子View设置为Gone状态。下面我们通过源码来详细解读这一过程。

ViewFlipper中的主要方法:

  1. @android.view.RemotableViewMethod
  2. public void setFlipInterval(int milliseconds) {
  3. mFlipInterval = milliseconds;
  4. }
  5. /**
  6. * Start a timer to cycle through child views
  7. */
  8. public void startFlipping() {
  9. mStarted = true;
  10. updateRunning();
  11. }
  12. /**
  13. * No more flips
  14. */
  15. public void stopFlipping() {
  16. mStarted = false;
  17. updateRunning();
  18. }
复制代码

  1. private void updateRunning(boolean flipNow) {
  2. boolean running = mVisible && mStarted && mUserPresent;
  3. if (running != mRunning) {
  4. if (running) {
  5. showOnly(mWhichChild, flipNow);
  6. postDelayed(mFlipRunnable, mFlipInterval);
  7. } else {
  8. removeCallbacks(mFlipRunnable);
  9. }
  10. mRunning = running;
  11. }
  12. if (LOGD) {
  13. Log.d(TAG, "updateRunning() mVisible=" + mVisible + ", mStarted=" + mStarted
  14. + ", mUserPresent=" + mUserPresent + ", mRunning=" + mRunning);
  15. }
  16. }
复制代码

看这三个方法,我们就能知道不管是startFlipper还是stopFlipper方法,他们都是调用了updateRunning方法,不同的只是他们对于mStart这个变量设置的值不同,mStart值也就决定了ViewFlipper是start还是stop。

updateRunning方法它主要就是根据running值来判断是发送消息到消息栈中,还是移除消息。

  1. private final Runnable mFlipRunnable = new Runnable() {
  2. @Override
  3. public void run() {
  4. if (mRunning) {
  5. showNext();
  6. postDelayed(mFlipRunnable, mFlipInterval);
  7. }
  8. }
  9. };
复制代码

如果是startFlipper,,也就是将下一个View的状态设置为Visible,其他的View设置为Gone状态。执行这一工作的方法为showNext()。此方法的实现在ViewAnimator。其实在ViewFlipper中,也就干了这么点事情。下面我们来看ViewAnimator。

ViewAnimator中的主要方法:

  1. public void showNext() {
  2. setDisplayedChild(mWhichChild + 1);
  3. }
复制代码

  1. public void setDisplayedChild(int whichChild) {
  2. mWhichChild = whichChild;
  3. if (whichChild >= getChildCount()) {
  4. mWhichChild = 0;
  5. } else if (whichChild < 0) {
  6. mWhichChild = getChildCount() - 1;
  7. }
  8. boolean hasFocus = getFocusedChild() != null;
  9. // This will clear old focus if we had it
  10. showOnly(mWhichChild);
  11. if (hasFocus) {
  12. // Try to retake focus if we had it
  13. requestFocus(FOCUS_FORWARD);
  14. }
  15. }
复制代码

这两个方法也就是计算出下一个View该显示哪个,确定了具体要显示的View后,就会调用showOnly(mWhichChild)方法

  1. void showOnly(int childIndex) {
  2. final int count = getChildCount();
  3. for (int i = 0; i < count; i++) {
  4. final View child = getChildAt(i);
  5. final boolean checkForFirst = (!mFirstTime || mAnimateFirstTime);
  6. if (i == childIndex) {
  7. if (checkForFirst && mInAnimation != null) {
  8. child.startAnimation(mInAnimation);
  9. }
  10. child.setVisibility(View.VISIBLE);
  11. mFirstTime = false;
  12. } else {
  13. if (checkForFirst && mOutAnimation != null && child.getVisibility() == View.VISIBLE) {
  14. child.startAnimation(mOutAnimation);
  15. } else if (child.getAnimation() == mInAnimation)
  16. child.clearAnimation();
  17. child.setVisibility(View.GONE);
  18. }
  19. }
  20. }
复制代码

这个方法主要的工作就是显示mWhichChild,将其他的设置为Gone状态。同时在这个方法中还会进行切换动画的调用,如果有动画的话。

其实在ViewAnimator类中,主要就是干了两件事,一件就是按照要求将需要显示的子view设置为Visible状态,其他的子View设置为Gone状态。另外一件就是动画的处理工作。

看完这个有没有发现其实ViewFlipper是这样的简单?



回复

使用道具 举报