ViewFlipper的使用

屏幕切换指的是在同一个Activity内屏幕见的切换,最长见的情况就是在一个FrameLayout内有多个页面,比如一个系统设置页面;一个个性化设置页面。


通过查看OPhone API文档可以发现,有个android.widget.ViewAnimator类继承至FrameLayout,ViewAnimator类的作用是为FrameLayout里面的View切换提供动画效果。该类有如下几个和动画相关的函数:


l setInAnimation: 设置View进入屏幕时候使用的动画,该函数有两个版本,一个接受单个参数,类型为android.view.animation.Animation; 一个接受两个参数,类型为Context和int,分别为Context对象和定义Animation的resourceID。


 


setOutAnimation: 设置View退出屏幕时候使用的动画,参数setInAnimation函数一样。


showNext: 调用该函数来显示FrameLayout里面的下一个View。


showPrevious: 调用该函数来显示FrameLayout里面的上一个View。


 


一 般不直接使用ViewAnimator而是使用它的两个子类ViewFlipper和ViewSwitcher。ViewFlipper可以用来指定 FrameLayout内多个View之间的切换效果,可以一次指定也可以每次切换的时候都指定单独的效果。该类额外提供了如下几个函数:


 


isFlipping: 用来判断View切换是否正在进行


setFilpInterval:设置View之间切换的时间间隔


startFlipping:使用上面设置的时间间隔来开始切换所有的View,切换会循环进行


stopFlipping: 停止View切换


ViewSwitcher 顾名思义Switcher特指在两个View之间切换。可以通过该类指定一个ViewSwitcher.ViewFactory 工程类来创建这两个View。该类也具有两个子类ImageSwitcher、TextSwitcher分别用于图片和文本切换。


在教程中通过示例介绍ViewFlipper 的使用,其他的使用方式是类似的。详细信息可以参考文档:


http://androidappdocs-staging.appspot.com/reference/android/widget/ViewAnimator.html

 


ViewFlipper示例


记 住,ViewFlipper是继承至FrameLayout的,所以它是一个Layout里面可以放置多个View。在示例中定义一个 ViewFlipper,里面包含三个ViewGroup作为示例的三个屏幕,每个ViewGroup中包含一个按钮和一张图片,点击按钮则显示下一个屏 幕。代码如下(res\layout\main.xml):


view plaincopy to clipboardprint?

 

  1. <?xml version="1.0" encoding="utf-8"?>    
  2.  
  3. <LinearLayout    
  4.  
  5.     xmlns:android="http://schemas.android.com/apk/res/android"   
  6.  
  7.     android:orientation="vertical"     
  8.  
  9.     android:layout_width="fill_parent"   
  10.  
  11.     android:layout_height="fill_parent">    
  12.  
  13.     <ViewFlipper android:id="@+id/details"   
  14.  
  15.        android:layout_width="fill_parent"     
  16.  
  17.        android:layout_height="fill_parent"   
  18.  
  19.        android:persistentDrawingCache="animation"   
  20.  
  21.        android:flipInterval="1000"   
  22.  
  23.        android:inAnimation="@anim/push_left_in"   
  24.  
  25. android:outAnimation="@anim/push_left_out"   
  26.  
  27. >     
  28.  
  29.        <LinearLayout    
  30.  
  31.            android:orientation="vertical"   
  32.  
  33.            android:layout_width="fill_parent"     
  34.  
  35.            android:layout_height="fill_parent">    
  36.  
  37.            <Button    
  38.  
  39.               android:text="Next"     
  40.  
  41.               android:id="@+id/Button_next1"   
  42.  
  43.               android:layout_width="fill_parent"     
  44.  
  45.               android:layout_height="wrap_content">    
  46.  
  47.            </Button>    
  48.  
  49.            <ImageView    
  50.  
  51.               android:id="@+id/p_w_picpath1"     
  52.  
  53.               android:src="@drawable/dell1"   
  54.  
  55.               android:layout_width="fill_parent"   
  56.  
  57.               android:layout_height="wrap_content">    
  58.  
  59.            </ImageView>    
  60.  
  61.        </LinearLayout>    
  62.  
  63.      
  64.  
  65.        <LinearLayout    
  66.  
  67.            android:orientation="vertical"   
  68.  
  69.            android:layout_width="fill_parent"     
  70.  
  71.            android:layout_height="fill_parent">    
  72.  
  73.            <Button    
  74.  
  75.               android:text="Next"     
  76.  
  77.               android:id="@+id/Button_next2"   
  78.  
  79.               android:layout_width="fill_parent"     
  80.  
  81.               android:layout_height="wrap_content">    
  82.  
  83.            </Button>    
  84.  
  85.            <ImageView    
  86.  
  87.               android:id="@+id/p_w_picpath2"     
  88.  
  89.               android:src="@drawable/lg"   
  90.  
  91.               android:layout_width="fill_parent"   
  92.  
  93.               android:layout_height="wrap_content">    
  94.  
  95.            </ImageView>    
  96.  
  97.        </LinearLayout>    
  98.  
  99.            
  100.  
  101.        <LinearLayout    
  102.  
  103.            android:orientation="vertical"   
  104.  
  105.            android:layout_width="fill_parent"     
  106.  
  107.            android:layout_height="fill_parent">    
  108.  
  109.            <Button    
  110.  
  111.               android:text="Next"     
  112.  
  113.               android:id="@+id/Button_next3"   
  114.  
  115.               android:layout_width="fill_parent"     
  116.  
  117.               android:layout_height="wrap_content">    
  118.  
  119.            </Button>    
  120.  
  121.            <ImageView    
  122.  
  123.               android:id="@+id/p_w_picpath3"     
  124.  
  125.               android:src="@drawable/lenovo"   
  126.  
  127.               android:layout_width="fill_parent"   
  128.  
  129.               android:layout_height="wrap_content">    
  130.  
  131.            </ImageView>    
  132.  
  133.        </LinearLayout>    
  134.  
  135.      
  136.  
  137.     </ViewFlipper>    
  138.  
  139.      
  140.  
  141. </LinearLayout>   

很 简单,在Layout定义中指定动画的相关属性就可以了,通过persistentDrawingCache指定缓存策略;flipInterval指定 每个View动画之间的时间间隔;inAnimation和outAnimation分别指定View进出使用的动画效果。动画效果定义如下:


view plaincopy to clipboardprint?

res\anim\push_left_in.xml   


 

  1. <?xml version="1.0" encoding="utf-8"?>    
  2.  
  3. <set xmlns:android="http://schemas.android.com/apk/res/android">    
  4.  
  5.     <translate    
  6.  
  7.     android:fromXDelta="100%p"     
  8.  
  9.     android:toXDelta="0"     
  10.  
  11.     android:duration="500"/>    
  12.  
  13.     <alpha    
  14.  
  15.     android:fromAlpha="0.0"     
  16.  
  17.     android:toAlpha="1.0"   
  18.  
  19.     android:duration="500" />    
  20.  
  21. </set>    
  22.  
  23. res\anim\push_left_out.xml    
  24.  
  25. <?xml version="1.0" encoding="utf-8"?>    
  26.  
  27. <set xmlns:android="http://schemas.android.com/apk/res/android">    
  28.  
  29.     <translate    
  30.  
  31.     android:fromXDelta="0"     
  32.  
  33.     android:toXDelta="-100%p"     
  34.  
  35.     android:duration="500"/>    
  36.  
  37.     <alpha    
  38.  
  39.     android:fromAlpha="1.0"     
  40.  
  41.     android:toAlpha="0.0"     
  42.  
  43.     android:duration="500" />    
  44.  
  45. </set>   

Activity代码如下(src\cc\c\TestActivity.java):


view plaincopy to clipboardprint?

  1. public class TestActivity extends Activity {    
  2.  
  3.     private ViewFlipper mViewFlipper;    
  4.  
  5.     @Override   
  6.  
  7.     public void onCreate(Bundle savedInstanceState) {    
  8.  
  9.         super.onCreate(savedInstanceState);    
  10.  
  11.         setContentView(R.layout.main);    
  12.  
  13.             
  14.  
  15.         Button buttonNext1 = (Button) findViewById(R.id.Button_next1);    
  16.  
  17.         mViewFlipper = (ViewFlipper) findViewById(R.id.flipper);    
  18.  
  19.         buttonNext1.setOnClickListener(new View.OnClickListener() {    
  20.  
  21.             public void onClick(View view) {    
  22.  
  23.                 //在layout中定义的属性,也可以在代码中指定    
  24.  
  25. //             mViewFlipper.setInAnimation(getApplicationContext(), R.anim.push_left_in);    
  26.  
  27. //             mViewFlipper.setOutAnimation(getApplicationContext(), R.anim.push_left_out);    
  28.  
  29. //             mViewFlipper.setPersistentDrawingCache(ViewGroup.PERSISTENT_ALL_CACHES);    
  30.  
  31. //             mViewFlipper.setFlipInterval(1000);    
  32.  
  33.                 mViewFlipper.showNext();    
  34.  
  35.                 //调用下面的函数将会循环显示mViewFlipper内的所有View。    
  36.  
  37. //             mViewFlipper.startFlipping();    
  38.  
  39.         }    
  40.  
  41.         });    
  42.  
  43.      
  44.  
  45.         Button buttonNext2 = (Button) findViewById(R.id.Button_next2);    
  46.  
  47.         buttonNext2.setOnClickListener(new View.OnClickListener() {    
  48.  
  49.             public void onClick(View view) {    
  50.  
  51.                 mViewFlipper.showNext();    
  52.  
  53.         }    
  54.  
  55.      
  56.  
  57.         });       
  58.  
  59.         Button buttonNext3 = (Button) findViewById(R.id.Button_next3);    
  60.  
  61.         buttonNext3.setOnClickListener(new View.OnClickListener() {    
  62.  
  63.             public void onClick(View view) {    
  64.  
  65.                 mViewFlipper.showNext();    
  66.  
  67.         }    
  68.  
  69.      
  70.  
  71.         });    
  72.  
  73.      
  74.  
  75.     }    
  76.  
  77.     }   

通过手势移动屏幕


上面是通过屏幕上的按钮来在屏幕间切换的,这看起来多少有点不符合OPhone的风格,如果要是能通过手势的左右滑动来实现屏幕的切换就比较优雅了。


通过android.view.GestureDetector类可以检测各种手势事件,该类有两个回调接口分别用来通知具体的事件:


 


GestureDetector.OnDoubleTapListener:用来通知DoubleTap事件,类似于鼠标的双击事件,该接口有如下三个回调函数:


 


1.   onDoubleTap(MotionEvent e):通知DoubleTap手势,


2.   onDoubleTapEvent(MotionEvent e):通知DoubleTap手势中的事件,包含down、up和move事件(这里指的是在双击之间发生的事件,例如在同一个地方双击会产生 DoubleTap手势,而在DoubleTap手势里面还会发生down和up事件,这两个事件由该函数通知);


3.   onSingleTapConfirmed(MotionEvent e):用来判定该次点击是SingleTap而不是DoubleTap,如果连续点击两次就是DoubleTap手势,如果只点击一次,OPhone系统 等待一段时间后没有收到第二次点击则判定该次点击为SingleTap而不是DoubleTap,然后触发SingleTapConfirmed事件。


GestureDetector.OnGestureListener:用来通知普通的手势事件,该接口有如下六个回调函数:


1.   onDown(MotionEvent e):down事件;


2.   onSingleTapUp(MotionEvent e):一次点击up事件;


3.   onShowPress(MotionEvent e):down事件发生而move或则up还没发生前触发该事件;


4.   onLongPress(MotionEvent e):长按事件;


5.   onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY):滑动手势事件;


6.   onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY):在屏幕上拖动事件。


 


这些事件有些定义的不太容易理解,在示例项目中实现了所有的回调函数,在每个函数中输出相关的日志,对这些事件不理解的可以运行项目,通过不同的操作来触发事件,然后观看logcat输出日志可有助于对这些事件的理解。


 


在 上述事件中,如果在程序中处理的该事件就返回true否则返回false,在GestureDetector中也定义了一个 SimpleOnGestureListener类,这是个助手类,实现了上述的所有函数并且都返回false。如果在项目中只需要监听某个事件继承这个 类可以少些几个空回调函数。


 


要走上面的程序中添加滑动手势来实现屏幕切换的话,首先需要定义一个GestureDetector:


private GestureDetector mGestureDetector;


 


并在onCreate函数中初始化:


mGestureDetector = new GestureDetector(this);


 


参数是OnGestureListener,然后让TestActivity实现 OnGestureListener 和OnDoubleTapListener接口:


 


 


view plaincopy to clipboardprint?

  1. class TestActivity extends Activity implements OnGestureListener , OnDoubleTapListener   

然后在onFling函数中实现切换屏幕的功能:


view plaincopy to clipboardprint?

  1. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,    
  2.  
  3.            float velocityY) {    
  4.  
  5.        Log.d(tag, "...onFling...");    
  6.  
  7.        if(e1.getX() > e2.getX()) {//move to left    
  8.  
  9.            mViewFlipper.showNext();    
  10.  
  11.        }else if(e1.getX() < e2.getX()) {    
  12.  
  13.            mViewFlipper.setInAnimation(getApplicationContext(), R.anim.push_right_in);    
  14.  
  15.            mViewFlipper.setOutAnimation(getApplicationContext(), R.anim.push_right_out);    
  16.  
  17.            mViewFlipper.showPrevious();    
  18.  
  19.            mViewFlipper.setInAnimation(getApplicationContext(), R.anim.push_left_in);    
  20.  
  21.            mViewFlipper.setOutAnimation(getApplicationContext(), R.anim.push_left_out);    
  22.  
  23.        }else {    
  24.  
  25.            return false;    
  26.  
  27.        }    
  28.  
  29.        return true;    
  30.  
  31.     }   

 


这里实现的功能是从右往左滑动则切换到上一个View,从左往右滑动则切换到下一个View,并且使用不同的in、out 动画使切换效果看起来统一一些。


然后在onDoubleTap中实现双击自动切换的效果,再次双击则停止:


   


view plaincopy to clipboardprint?

  1. public boolean onDoubleTap(MotionEvent e) {    
  2.  
  3.        Log.d(tag, "...onDoubleTap...");    
  4.  
  5.        if(mViewFlipper.isFlipping()) {    
  6.  
  7.            mViewFlipper.stopFlipping();    
  8.  
  9.        }else {    
  10.  
  11.            mViewFlipper.startFlipping();    
  12.  
  13.        }    
  14.  
  15.        return true;    
  16.  
  17.     }   

 


到这里手势代码就完成了,现在可以通过左右滑动切换View并且双击可以自动切换View。细心的读者这里可能会发现一个问题,上面在创建mGestureDetector 的时候使用的是如下代码:


mGestureDetector = new GestureDetector(this);


 


这 里的参数为OnGestureListener,而且GestureDetector有个函数setOnDoubleTapListener来设置 OnDoubleTapListener,在上面的代码中并没有设置OnDoubleTapListener,那么onDoubleTap事件是如何调用 的呢?这里的玄机就要去探探 GestureDetector(OnGestureListener l)这个构造函数的源代码了:


view plaincopy to clipboardprint?

    public GestureDetector(OnGestureListener listener) {   


        this(null, listener, null);   


}  


 


调用了另外一个构造函数:


   


view plaincopy to clipboardprint?

  1. public GestureDetector(Context context, OnGestureListener listener, Handler handler) {    
  2.  
  3.        if (handler != null) {    
  4.  
  5.            mHandler = new GestureHandler(handler);    
  6.  
  7.        } else {    
  8.  
  9.            mHandler = new GestureHandler();    
  10.  
  11.        }    
  12.  
  13.        mListener = listener;    
  14.  
  15.        if (listener instanceof OnDoubleTapListener) {    
  16.  
  17.            setOnDoubleTapListener((OnDoubleTapListener) listener);    
  18.  
  19.        }    
  20.  
  21.        init(context);    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章