Android学习笔记_21_ViewFlipper使用详解

来源:互联网 发布:幸运大转盘抽奖软件 编辑:程序博客网 时间:2024/06/07 11:42

一、介绍ViewFilpper类

1.1 屏幕切换

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

1.2 ViewFilpper类

     ViewFlipper extends ViewAnimator

 

 

java.lang.Object   ↳android.view.View    ↳android.view.ViewGroup     ↳android.widget.FrameLayout      ↳android.widget.ViewAnimator       ↳android.widget.ViewFlipper

Class Overview

Simple ViewAnimator that will animate between two or more views that have been added to it. Only one child is shown at a time. If requested, can automatically flip between each child at a regular interval.

    意思是:简单的ViewAnimator之间,两个或两个以上的view加上动画效果。只有一个小孩会显示在一个时间。如果需要,每个孩子能自动翻转之间在固定的时间间隔。

   该类继承了Framelayout类,ViewAnimator类的作用是为FrameLayout里面的View切换提供动画效果。
   该类有如下几个和动画相关的函数:

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

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

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

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

    简单ViewFlipper的应用

二、ViewFlipper复杂应用

2.1 动态添加多个View

   下面通过一个Demo了解一下ViewFlipper的用法
 

main.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     android:orientation="vertical" >      <ViewFlipper         android:id="@+id/viewFlipper"         android:layout_width="fill_parent"         android:layout_height="fill_parent" >          <include             android:id="@+id/layout01"             layout="@layout/layout01" />          <include             android:id="@+id/layout02"             layout="@layout/layout02" />     </ViewFlipper>  </LinearLayout> 

  layout01.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     android:orientation="vertical" >      <TextView         android:layout_width="fill_parent"         android:layout_height="fill_parent"         android:gravity="center"         android:text="一个TextView"         android:textSize="40dip" />  </LinearLayout> 

  layout02.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     android:orientation="vertical" >      <LinearLayout         android:layout_width="fill_parent"         android:layout_height="fill_parent"         android:gravity="center"         android:orientation="vertical" >          <ImageView             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:src="@drawable/ic_launcher" />          <TextView             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:text="一个TextView + 一个ImageView"             android:textSize="20dip" />     </LinearLayout>  </LinearLayout> 

  ViewFlipperDemoActivity.java

package com.tianjf;  import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.animation.AnimationUtils; import android.widget.ViewFlipper;  public class ViewFlipperDemoActivity extends Activity implements         OnTouchListener {      private ViewFlipper viewFlipper;      // 左右滑动时手指按下的X坐标     private float touchDownX;     // 左右滑动时手指松开的X坐标     private float touchUpX;      @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.main);          viewFlipper = (ViewFlipper) findViewById(R.id.viewFlipper);         viewFlipper.setOnTouchListener(this);     }      @Override     public boolean onTouch(View v, MotionEvent event) {         if (event.getAction() == MotionEvent.ACTION_DOWN) {             // 取得左右滑动时手指按下的X坐标             touchDownX = event.getX();             return true;         } else if (event.getAction() == MotionEvent.ACTION_UP) {             // 取得左右滑动时手指松开的X坐标             touchUpX = event.getX();             // 从左往右,看前一个View             if (touchUpX - touchDownX > 100) {                 // 设置View切换的动画                 viewFlipper.setInAnimation(AnimationUtils.loadAnimation(this,                         android.R.anim.slide_in_left));                 viewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,                         android.R.anim.slide_out_right));                 // 显示下一个View                 viewFlipper.showPrevious();                 // 从右往左,看后一个View             } else if (touchDownX - touchUpX > 100) {                 // 设置View切换的动画                 // 由于Android没有提供slide_out_left和slide_in_right,所以仿照slide_in_left和slide_out_right编写了slide_out_left和slide_in_right                 viewFlipper.setInAnimation(AnimationUtils.loadAnimation(this,                         R.anim.slide_in_right));                 viewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,                         R.anim.slide_out_left));                 // 显示前一个View                 viewFlipper.showNext();             }             return true;         }         return false;     } } 

  slide_in_right.xml

<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android">     <translate android:fromXDelta="50%p" android:toXDelta="0" android:duration="300"/>     <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" /> </set> 

  slide_out_left.xml

<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android">     <translate android:fromXDelta="0" android:toXDelta="-50%p" android:duration="300"/>     <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="300" /> </set> 

上面的例子是在布局文件中为ViewFlipper固定添加了两个View,如果现在有N个View怎么办呢?那么我们就需要在Java代码里面动态的添加View,如下部分.

  main.xml布局文件

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     android:orientation="vertical" >      <com.tianjf.MyViewFlipper         android:id="@+id/myViewFlipper"         android:layout_width="fill_parent"         android:layout_height="fill_parent"         android:background="@android:color/white"         android:gravity="center" >     </com.tianjf.MyViewFlipper>  </LinearLayout> 

    flipper_view.xml布局文件

<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     android:scrollbars="none" >      <LinearLayout         android:layout_width="fill_parent"         android:layout_height="wrap_content"         android:gravity="center"         android:orientation="vertical" >          <ImageView             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:src="@drawable/ic_launcher" />          <TextView             android:id="@+id/textView"             android:textSize="100dip"             android:layout_width="wrap_content"             android:layout_height="wrap_content" />     </LinearLayout>  </ScrollView> 

 

package com.tianjf;  import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent;  public class MyGestureListener extends SimpleOnGestureListener {          private OnFlingListener mOnFlingListener;      public OnFlingListener getOnFlingListener() {         return mOnFlingListener;     }      public void setOnFlingListener(OnFlingListener mOnFlingListener) {         this.mOnFlingListener = mOnFlingListener;     }      @Override     public final boolean onFling(final MotionEvent e1, final MotionEvent e2,             final float speedX, final float speedY) {         if (mOnFlingListener == null) {             return super.onFling(e1, e2, speedX, speedY);         }          float XFrom = e1.getX();         float XTo = e2.getX();         float YFrom = e1.getY();         float YTo = e2.getY();         // 左右滑动的X轴幅度大于100,并且X轴方向的速度大于100         if (Math.abs(XFrom - XTo) > 100.0f && Math.abs(speedX) > 100.0f) {             // X轴幅度大于Y轴的幅度             if (Math.abs(XFrom - XTo) >= Math.abs(YFrom - YTo)) {                 if (XFrom > XTo) {                     // 下一个                     mOnFlingListener.flingToNext();                 } else {                     // 上一个                     mOnFlingListener.flingToPrevious();                 }             }         } else {             return false;         }         return true;     }      public interface OnFlingListener {         void flingToNext();          void flingToPrevious();     } } 
MyViewFlipper.java[java]package com.tianjf;  import com.tianjf.MyGestureListener.OnFlingListener;  import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import android.widget.ViewFlipper;  public class MyViewFlipper extends ViewFlipper implements OnFlingListener {      private GestureDetector mGestureDetector = null;      private OnViewFlipperListener mOnViewFlipperListener = null;      public MyViewFlipper(Context context) {         super(context);     }      public MyViewFlipper(Context context, AttributeSet attrs) {         super(context, attrs);     }      public void setOnViewFlipperListener(OnViewFlipperListener mOnViewFlipperListener) {         this.mOnViewFlipperListener = mOnViewFlipperListener;         MyGestureListener myGestureListener = new MyGestureListener();         myGestureListener.setOnFlingListener(this);         mGestureDetector = new GestureDetector(myGestureListener);     }      @Override     public boolean onInterceptTouchEvent(MotionEvent ev) {         if (null != mGestureDetector) {             return mGestureDetector.onTouchEvent(ev);         } else {             return super.onInterceptTouchEvent(ev);         }     }      @Override     public void flingToNext() {         if (null != mOnViewFlipperListener) {             int childCnt = getChildCount();             if (childCnt == 2) {                 removeViewAt(1);             }             addView(mOnViewFlipperListener.getNextView(), 0);             if (0 != childCnt) {                 setInAnimation(getContext(), R.anim.left_slip_in);                 setOutAnimation(getContext(), R.anim.left_slip_out);                 setDisplayedChild(0);             }         }     }      @Override     public void flingToPrevious() {         if (null != mOnViewFlipperListener) {             int childCnt = getChildCount();             if (childCnt == 2) {                 removeViewAt(1);             }             addView(mOnViewFlipperListener.getPreviousView(), 0);             if (0 != childCnt) {                 setInAnimation(getContext(), R.anim.right_slip_in);                 setOutAnimation(getContext(), R.anim.right_slip_out);                 setDisplayedChild(0);             }         }     }      public interface OnViewFlipperListener {         View getNextView();          View getPreviousView();     } } ViewFlipperDemoActivity.java[java]package com.tianjf;  import com.tianjf.MyViewFlipper.OnViewFlipperListener;  import android.app.Activity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.ScrollView; import android.widget.TextView;  public class ViewFlipperDemoActivity extends Activity implements OnViewFlipperListener {      private MyViewFlipper myViewFlipper;     private int currentNumber;      @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.main);          currentNumber = 1;         myViewFlipper = (MyViewFlipper) findViewById(R.id.myViewFlipper);         myViewFlipper.setOnViewFlipperListener(this);         myViewFlipper.addView(creatView(currentNumber));     }      @Override     public View getNextView() {         currentNumber = currentNumber == 10 ? 1 : currentNumber + 1;         return creatView(currentNumber);     }      @Override     public View getPreviousView() {         currentNumber = currentNumber == 1 ? 10 : currentNumber - 1;         return creatView(currentNumber);     }      private View creatView(int currentNumber) {         LayoutInflater layoutInflater = LayoutInflater.from(this);         ScrollView resultView = (ScrollView) layoutInflater.inflate(R.layout.flipper_view, null);         ((TextView) resultView.findViewById(R.id.textView)).setText(currentNumber + "");         return resultView;     } } 

 

  ViewFilpper的showPrevious()方法和showNext()方法是用来显示已经在布局文件中定义好了的View,现在我们没有在布局文件中为ViewFlipper添加View,那么showPrevious()方法和showNext()方法就不能用了。但是我们怎么实现滑动来切换View呢?用什么方法呢?这时候,我们就要自定义一个MyViewFlipper来监听滑动事件,并做切换视图的处理。你可以让MyViewFlipper实现OnTouchListener接口,然后实现onTouch方法,然后根据MotionEvent.ACTION_DOWN和MotionEvent.ACTION_UP的坐标判断是不是滑动事件,就像ImageSwitcher中讲解的那样(http://blog.csdn.net/tianjf0514/article/details/7556487)  除了自己判断是不是滑动事件,那么Android有没有直接提供哪个方法作为滑动事件的回调函数呢?答案是:提供了。OnGestureListener中的onFling方法就是滑动事件的回调函数。这时候你也许会毫不犹豫的让MyViewFlipper实现OnGestureListener接口,并复写onFling方法。这样做当然可以,不过实现OnGestureListener接口不仅仅要复写onFling方法,还要复写其他的方法(onDown()、onShowPress()、onSingleTapUp()、onScroll()、onLongPress()),但是这些回调函数我们不需要,这就造成了垃圾代码。  为了避免垃圾代码,Android提供了一个类SimpleOnGestureListener已经实现了OnGestureListener接口和OnDoubleTapListener接口,并复写了所有方法。那么我们只要新建一个自己的MyGestureListener.java来继承SimpleOnGestureListener,并有选择性的复写需要的方法(我们在此只复写onFling方法)。  这时,我们就自定义了一个手势类,并且这个手势类会监听滑动事件来做一些处理。但是我们怎么利用这个手势类呢?怎么利用到MyViewFlipper类中去呢?  关于onFling方法,有一点要注意:不是每个View都能有onFling回调函数,一开始,我的flipper_view.xml布局文件最外层是一个LinearLayout,死活都走不到onFling方法,后来在外层又套了一个ScrollView,就能正常走到OnFling方法里面了。  可以看到flingToNext方法和flingToPrevious方法里面会判断childCnt,如果为2,就removeViewAt(1);,然后再addView(mOnViewFlipperListener.getNextView(), 0);。这就要回顾一下ImageSwitcher的原理,ViewFlipper的原理和ImageSwitcher一样,有且仅有2个子View,滑动时候就在这两个子View上来回切换。index为0的就是当前看到的,index为1的就是看不见的。上面代码的意思就是:当滑动时,必然要新添加一个View,那么子View的个数有可能大于2,随意要先判断一下如果childCnt == 2,那么就把index == 1的那个View(即看不见的View)给Remove调,然后把新添加的View添加到index == 0处。这样可以减少内存消耗。OK,这个例子的基本的注意点已经讲完了。下面在系统的回顾一下这个例子的具体流程。在我们滑动手机屏幕的时候(假设我们从右往左滑动),那么应该显示下一个View。调用onFling方法中的mOnFlingListener.flingToNext();flingToNext方法的是实现在MyViewFlipper类中,调用flingToNext方法的addView(mOnViewFlipperListener.getNextView(), 0);getNextView的实现在ViewFlipperDemoActivity类中

 

 

0 0
原创粉丝点击