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);    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章