关于ViewPager、ViewFilpper、ViewFlow,Gallery四种实现水平滑动方式的比较


ViewPager

ViewPager类提供了多界面切换的新效果。新效果有如下特征:

[1] 当前显示一组界面中的其中一个界面。

[2] 当用户通过左右滑动界面时,当前的屏幕显示当前界面和下一个界面的一部分。

[3] 滑动结束后,界面自动跳转到当前选择的界面中

 

ViewPager来源于google 的补充组件android-support-v4.jar,位置在androidSDK文件夹

android-sdks\extras\android\support\ 下 

将android-support-v4.jar 引用到项目中

注:该包需要在Android SDK Manager中额外下载Extras下的Android Support package,

或直接下载该jar包到项目中引用

 

引入后可直接当作控件在项目中使用。

配置文件页面文件

View Code
1 <android.support.v4.view.ViewPager
2
3          android:id="@+id/viewPager1"
4
5          android:layout_width="fill_parent"
6
7          android:layout_height="fill_parent"
8
9          android:layout_centerVertical="true"  />

 

初始化控件

View Code
1 viewPager1 = (ViewPager) findViewById(R.id.viewPager1);
2
3         viewPager1.setAdapter(new PageAdapter(new ArrayList<View>()));

 

配置适配器的页面变化事件

View Code
 1 viewPager1
 2
 3        .setOnPageChangeListener(new OnPageChangeListener() {
 4
 5             //页面选择
 6
 7 @Override
 8
 9            public void onPageSelected(int position) {
10
11               topText.setText(String.valueOf(position+1)+"/"+String.valueOf(lists.length));
12
13            }
14
15
16
17            @Override
18
19            public void onPageScrollStateChanged(int state) {
20
21            }
22
23
24
25            @Override
26
27            public void onPageScrolled(int position,
28
29                   float positionOffset, int positionOffsetPixels) {
30
31            }
32
33        });

 

ViewPager使用的适配器基于PagerAdapter基类

主要实现一下四个方法

View Code
 1 //获取当前窗体界面数
 2
 3 public int getCount()
 4
 5 //初始化position位置的界面
 6
 7 public Object instantiateItem(View collection, int position)
 8
 9 //销毁position位置的界面
10
11 public void destroyItem(View collection, int position, Object view)
12
13 // 判断是否由对象生成界面
14
15 public boolean isViewFromObject(View arg0, Object arg1)

 

ViewPager控件的使用中,可以将View装如ArrayList中作为数据载体,每一项(即每一页)

为一个View显示,可以适应大量页面或者变化的页面长度的显示

  

======================

<?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" >

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" >

        <android.support.v4.view.PagerTitleStrip
            android:id="@+id/pagertitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top" />
    </android.support.v4.view.ViewPager>

</LinearLayout>

其中ViewPager为多页显示控件,PagerTitleStrip用于显示当前页面的标题

主窗口代码:

PagerTitleDemoActivity.java

package com.ns.pager;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.PagerTitleStrip;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;

public class PagerTitleDemoActivity extends Activity {
    /** Called when the activity is first created. */
    private ViewPager mViewPager;
    private PagerTitleStrip mPagerTitleStrip;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mViewPager = (ViewPager)findViewById(R.id.viewpager);
        mPagerTitleStrip = (PagerTitleStrip)findViewById(R.id.pagertitle);
        
        //将要分页显示的View装入数组中
        LayoutInflater mLi = LayoutInflater.from(this);
        View view1 = mLi.inflate(R.layout.view1, null);
        View view2 = mLi.inflate(R.layout.view2, null);
        View view3 = mLi.inflate(R.layout.view3, null);
        
        //每个页面的Title数据
        final ArrayList<View> views = new ArrayList<View>();
        views.add(view1);
        views.add(view2);
        views.add(view3);
        
        final ArrayList<String> titles = new ArrayList<String>();
        titles.add("tab1");
        titles.add("tab2");
        titles.add("tab3");
        
        //填充ViewPager的数据适配器
        PagerAdapter mPagerAdapter = new PagerAdapter() {
            
            @Override
            public boolean isViewFromObject(View arg0, Object arg1) {
                return arg0 == arg1;
            }
            
            @Override
            public int getCount() {
                return views.size();
            }

            @Override
            public void destroyItem(View container, int position, Object object) {
                ((ViewPager)container).removeView(views.get(position));
            }

            @Override
            public CharSequence getPageTitle(int position) {
                return titles.get(position);
            }

            @Override
            public Object instantiateItem(View container, int position) {
                ((ViewPager)container).addView(views.get(position));
                return views.get(position);
            }
        };
        
        mViewPager.setAdapter(mPagerAdapter);
    }
}






ViewFilpper

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

 

ViewFilpper控件是系统自带控件之一,主要是为两个页面间的切换设置动画效果。ViewFilpper继承自FrameLayout下的ViewAnimator,

 

android.widget.ViewAnimator类继承至FrameLayout,ViewAnimator类的作用是为FrameLayout里面的View切换提供动画效果。该类有如下几个和动画相关的函数: 
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切换 

ViewFilpper的使用方法:

配置页面文件

View Code
 1 <ViewFlipper
 2
 3         android:id="@+id/flipper"
 4
 5         android:layout_width="fill_parent"
 6
 7         android:layout_height="fill_parent"
 8
 9         android:layout_below="@+id/CockpitLayout" >
10
11         <include
12
13             android:id="@+id/secondlayout"
14
15             layout="@layout/second" >
16
17         </include>
18
19         <include
20
21             android:id="@+id/firstlayout"
22
23             layout="@layout/first" >
24
25         </include>
26
27 </ViewFlipper>

 

配置好页面文件后便可在代码中对ViewFilpper进行操作和设置切换动画

==========================

1)View切换的控件—ViewFlipper介绍

ViewFilpper类继承于ViewAnimator类。而ViewAnimator类继承于FrameLayout。

查看ViewAnimator类的源码可以看出此类的作用主要是为其中的View切换提供动画效果。该类有如下几个和动画相关的方法。

setInAnimation:设置View进入屏幕时候使用的动画。该方法有两个重载方法,即可以直接传入Animation对象,也可以传入定义的Animation文件的resourceID。

setOutAnimation:设置View退出屏幕时候使用的动画。使用方法和setInAnimation方法一样。

showNext:调用该方法可以显示FrameLayout里面的下一个View。

showPrevious:调用该方法可以来显示FrameLayout里面的上一个View。

查看ViewFlipper的源码可以看到,ViewFlipper主要用来实现View的自动切换。该类提供了如下几个主要的方法。

setFilpInterval:设置View切换的时间间隔。参数为毫秒。

startFlipping:开始进行View的切换,时间间隔是上述方法设置的间隔数。切换会循环进行。

stopFlipping:停止View切换。

setAutoStart:设置是否自动开始。如果设置为“true”,当ViewFlipper显示的时候View的切换会自动开始。

一般情况下,我们都会使用ViewFilpper类实现View的切换,而不使用它的父类ViewAnimator类。

2)实现滑动—GestureDetector介绍

如果想要实现滑动翻页的效果,就要了解另外一个类:android.view.GestureDetector类。GestureDetector类中可以用来检测各种手势事件。该类有两个回调接口,分别用来通知具体的事件。

GestureDetector.OnDoubleTapListener:用来通知DoubleTap事件,类似于PC上面的鼠标的双击事件。

GestureDetector.OnGestureListener:用来通知普通的手势事件,该接口有六个回调方法,具体的可以查看API。这里想要实现滑动的判断,就需要用到其中的onFling()方法。

3)具体的实现

下面的代码片段详细说明了如何实现滑动翻页。

<?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/viewFlipper1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:src="@drawable/b" />
         <ImageView
            android:id="@+id/imageView2"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:src="@drawable/c" />
          <ImageView
            android:id="@+id/imageView3"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:src="@drawable/d" />
          <ImageView
            android:id="@+id/imageView4"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:src="@drawable/f" />
         <ImageView
            android:id="@+id/imageView5"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:src="@drawable/g" />
    </ViewFlipper>

</LinearLayout>

public class ViewFlipperActivity extends Activity implements OnTouchListener, android.view.GestureDetector.OnGestureListener {
    private ViewFlipper flipper;
    GestureDetector mGestureDetector;  
    private int mCurrentLayoutState;  
    private static final int FLING_MIN_DISTANCE = 80;  
    private static final int FLING_MIN_VELOCITY = 150;  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.viewflipper);
        
        flipper=(ViewFlipper) this.findViewById(R.id.viewFlipper1);
         //注册一个用于手势识别的类  
        mGestureDetector = new GestureDetector(this);  
        //给mFlipper设置一个listener  
        flipper.setOnTouchListener(this);  
        mCurrentLayoutState = 0;  
        //允许长按住ViewFlipper,这样才能识别拖动等手势  
        flipper.setLongClickable(true);  
        
    }
    /**  
     * 此方法在本例中未用到,可以指定跳转到某个页面  
     * @param switchTo  
     */  
    public void switchLayoutStateTo(int switchTo) {  
        while (mCurrentLayoutState != switchTo)   {  
            if (mCurrentLayoutState > switchTo) {  
                mCurrentLayoutState--;  
                flipper.setInAnimation(inFromLeftAnimation());  
                flipper.setOutAnimation(outToRightAnimation());  
                flipper.showPrevious();  
            } else {  
                mCurrentLayoutState++;  
                flipper.setInAnimation(inFromRightAnimation());  
                flipper.setOutAnimation(outToLeftAnimation());  
                flipper.showNext();  
            }  
   
        }  
 
    } 
    /**  
     * 定义从右侧进入的动画效果  
     * @return  
     */  
    protected Animation inFromRightAnimation() {  
        Animation inFromRight = new TranslateAnimation(  
                Animation.RELATIVE_TO_PARENT, +1.0f,  
                Animation.RELATIVE_TO_PARENT, 0.0f,  
                Animation.RELATIVE_TO_PARENT, 0.0f,  
                Animation.RELATIVE_TO_PARENT, 0.0f);  
        inFromRight.setDuration(200);  
        inFromRight.setInterpolator(new AccelerateInterpolator());  
        return inFromRight;  
    }  
   
    /**  
     * 定义从左侧退出的动画效果  
     * @return  
     */  
    protected Animation outToLeftAnimation() {  
        Animation outtoLeft = new TranslateAnimation(  
                Animation.RELATIVE_TO_PARENT, 0.0f,  
                Animation.RELATIVE_TO_PARENT, -1.0f,  
                Animation.RELATIVE_TO_PARENT, 0.0f,  
                Animation.RELATIVE_TO_PARENT, 0.0f);  
        outtoLeft.setDuration(200);  
        outtoLeft.setInterpolator(new AccelerateInterpolator());  
        return outtoLeft;  
    }  
   
    /**  
     * 定义从左侧进入的动画效果  
     * @return  
     */  
    protected Animation inFromLeftAnimation() {  
        Animation inFromLeft = new TranslateAnimation(  
                Animation.RELATIVE_TO_PARENT, -1.0f,  
                Animation.RELATIVE_TO_PARENT, 0.0f,  
                Animation.RELATIVE_TO_PARENT, 0.0f,  
                Animation.RELATIVE_TO_PARENT, 0.0f);  
        inFromLeft.setDuration(200);  
        inFromLeft.setInterpolator(new AccelerateInterpolator());  
        return inFromLeft;  
    }  
    
    /**  
     * 定义从右侧退出时的动画效果  
     * @return  
     */  
    protected Animation outToRightAnimation() {  
        Animation outtoRight = new TranslateAnimation(  
                Animation.RELATIVE_TO_PARENT, 0.0f,  
                Animation.RELATIVE_TO_PARENT, +1.0f,  
                Animation.RELATIVE_TO_PARENT, 0.0f,  
                Animation.RELATIVE_TO_PARENT, 0.0f);  
        outtoRight.setDuration(200);  
        outtoRight.setInterpolator(new AccelerateInterpolator());  
        return outtoRight;  
    }  
    
    public boolean onDown(MotionEvent e) {
        // TODO Auto-generated method stub
        return false;
    }
    /*  
     * 用户按下触摸屏、快速移动后松开即触发这个事件  
     * e1:第1个ACTION_DOWN MotionEvent  
     * e2:最后一个ACTION_MOVE MotionEvent  
     * velocityX:X轴上的移动速度,像素/秒  
     * velocityY:Y轴上的移动速度,像素/秒  
     * 触发条件 :  
     * X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒  
     */
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
         if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE  
                    && Math.abs(velocityX) > FLING_MIN_VELOCITY) {  
                // 当像左侧滑动的时候  
                //设置View进入屏幕时候使用的动画  
                flipper.setInAnimation(inFromRightAnimation());  
                //设置View退出屏幕时候使用的动画  
                flipper.setOutAnimation(outToLeftAnimation());  
                flipper.showNext();  
            } else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE  
                    && Math.abs(velocityX) > FLING_MIN_VELOCITY) {  
                // 当像右侧滑动的时候  
                flipper.setInAnimation(inFromLeftAnimation());  
                flipper.setOutAnimation(outToRightAnimation());  
                flipper.showPrevious();  
            }  
            return false;  
    }
    public void onLongPress(MotionEvent e) {
        // TODO Auto-generated method stub
        
    }
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
            float distanceY) {
        // TODO Auto-generated method stub
        return false;
    }
    public void onShowPress(MotionEvent e) {
        // TODO Auto-generated method stub
        
    }
    public boolean onSingleTapUp(MotionEvent e) {
        // TODO Auto-generated method stub
        return false;
    }
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
          // 一定要将触屏事件交给手势识别类去处理(自己处理会很麻烦的)  
        return mGestureDetector.onTouchEvent(event);  
    }
    
    
}





ViewFlow

android-viewflow 是 Android 平台上一个视图切换的效果库。

ViewFlow 相当于 Android UI 部件提供水平滚动的 ViewGroup,使用 Adapter 进行条目绑定。文档上说,当你需要在一系列不确定数目的view中滑动时,可以考虑使用ViewFlow。如果你的view数目确定,你应该使用 Fragments 或兼容库里的ViewPager 。

 

1、使用ViewFlow

怎么使用呢?首先在你的layout文件中加入:

<org.taptwo.android.widget.ViewFlow

android:id="@+id/viewflow"

app:sidebuffer="5"

/>

其中app:sidebuffer属性是ViewFlow组件自定义的,使用这些属性时,需要增加如下的xml的命名空间:

xmlns:app="http://schemas.android.com/apk/res/your.application.package.here"

然后在你的Activity里面添加如下代码用于使用ViewFlow:

View Code
 1 ViewFlow viewFlow = (ViewFlow) findViewById(R.id.viewflow);
 2
 3 viewFlow.setAdapter(myAdapter);
 4
 5 //设置初始view的位置
 6
 7 //viewFlow.setAdapter(myAdapter, 8);
 8
 9 //监听view切换事件,简单的需求可不监听
10
11 viewFlow.setOnViewSwitchListener(new ViewSwitchListener() {
12
13     public void onSwitched(View v, int position) {
14
15     / / Your code here
16
17     }
18
19 });

 

当然,你也可以使用该库中的FlowIndicator为你在多个view中切换时提供一个指示器,目前该库已经实现了两种指示器:一种是圆点指示器FlowIndicator;另一种是标题指示器TitleFlowIndicator。

1、使用圆点指示器

圆点指示器可以这样使用:
先在layout中这样定义

View Code
1 <org.taptwo.android.widget.CircleFlowIndicator
2
3 android:padding="10dip" android:layout_height="wrap_content"
4
5 android:layout_width="wrap_content" android:id="@+id/viewflowindic"
6
7 android:background="#00000000"
8
9 />

 

然后在activity中调用它

View Code
1 CircleFlowIndicator indic = (CircleFlowIndicator)
2
3                      findViewById(R.id.viewflowindic);
4
5 viewFlow.setFlowIndicator(indic);

 

圆点指示器还支持activeColor、inactiveColor、activeType(填充或描边)、inactiveType(填充或描边)、fadeOut(设置圆点自动隐藏的秒数,若为0则不会自动隐藏)、radius(圆点的半径)等。

2、使用标题指示器

标题指示器也是先layout里定义:

View Code
 1 <org.taptwo.android.widget.TitleFlowIndicator
 2
 3 android:id="@+id/viewflowindic"
 4
 5         android:layout_height="wrap_content"
 6
 7 android:layout_width="fill_parent"
 8
 9 app:footerLineHeight="2dp"
10
11 app:footerTriangleHeight="10dp"
12
13         app:textColor="#FFFFFFFF" app:selectedColor="#FFFFC445"
14
15 app:footerColor="#FFFFC445" app:titlePadding="10dp"
16
17         app:textSize="11dp" app:selectedSize="12dp"
18
19 android:layout_marginTop="10dip"
20
21 app:clipPadding="5dp" />

 

然后在activity中调用它:

View Code
1 TitleFlowIndicator indicator = (TitleFlowIndicator)
2
3                           findViewById(R.id.viewflowindic);
4
5 indicator.setTitleProvider(myTitleProvider);
6
7 viewFlow.setFlowIndicator(indicator);

 

以上就是ViewFlow库提供三大组件及其用法(来自其文档),使用时需要下载到其代码并放在你的项目中的某个包内,当然你也可以把该组件库打包成jar调用。

=================


Gallery

package xiaosi.gallery;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.Toast;

public class GalleryActivity extends Activity {
    /** Called when the activity is first created. */
    private Gallery gallery =null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        gallery = (Gallery)findViewById(R.id.gallery);
        //设置图片适配器
        gallery.setAdapter(new ImageAdapter(this));
        gallery.setSpacing(5);
        
        //设置监听器
        gallery.setOnItemClickListener(new OnItemClickListener() {
            
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,    long arg3) {
                Toast.makeText(GalleryActivity.this, "点击了第"+arg2+"张图片", Toast.LENGTH_LONG).show();
            }
        });
    }
}

class ImageAdapter extends BaseAdapter{
    
    int mGalleryItemBackground;
    private Context context;
    //图片源数组
    private Integer[] imageInteger={
            R.drawable.a,
            R.drawable.b,
            R.drawable.c,
            R.drawable.d
    };
    public ImageAdapter(Context c){
        context = c;
        TypedArray attr = context.obtainStyledAttributes(R.styleable.HelloGallery);        
        mGalleryItemBackground = attr.getResourceId(R.styleable.HelloGallery_android_galleryItemBackground, 0);        
        attr.recycle();
    }
    // 获取图片的个数
    public int getCount() {
        return imageInteger.length;
    }
    // 获取图片在库中的位置  
    public Object getItem(int position) {
        return position;
    }
    // 获取图片ID  
    public long getItemId(int position) {
        return position;
    }
    public View getView(int position, View convertView, ViewGroup parent) {
        
        ImageView imageView = new ImageView(context);
        // 给ImageView设置资源
        imageView.setImageResource(imageInteger[position]);
        // 设置显示比例类型  
        imageView.setScaleType(ImageView.ScaleType.FIT_XY);
        // 设置布局 图片120*80 
        imageView.setLayoutParams(new Gallery.LayoutParams(180, 100));
        imageView.setBackgroundResource(mGalleryItemBackground);        
        return imageView;
    }
}


 

<?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" >

    <Gallery
        android:id="@+id/gallery"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="bottom"
        android:background="?android:galleryItemBackground"/>
</LinearLayout>

创建一个新的XML文件在res/values/目录下 attrs.xml命名。

这是一个定制的styleable资源,可以应用于一个布局。


<?xml version="1.0" encoding="utf-8"?>
<resources>    
    <declare-styleable name="HelloGallery">       
         <attr name="android:galleryItemBackground" />    
    </declare-styleable>
</resources>

http://www.cnblogs.com/bill-joy/archive/2012/04/09/2438688.html



比较

根据以上对三种实现的使用描述,可以看出,ViewPager与ViewFlow都能够使用适配器进行大量数据的适配。并且ViewFlow也带有 原点和标题的位置提示,二者比较相像。ViewFilpper使用时主要是在有限的少数页面切换中比较合适,并且能够自定义每一个切换动画,用于一个应用 间的画面切换比较合适,类似于ActivityGroup。

ViewFlow由于提供源码,所以在扩展性上更强,可根据需要自行定制,比如加入循环播放等。

你可能感兴趣的:(viewpager,viewflow,gallery,ViewFilpper)