关于ViewPager、ViewFilpper、ViewFlow,Gallery四种实现水平滑动方式的比较
2014-01-08 14:46
671 查看
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、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较(转)
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- 关于ViewPager、ViewFilpper、ViewFlow三种实现水平向滑动方式的比较
- android 三种实现水平向滑动方式(ViewPager、ViewFilpper、ViewFlow)的比较
- android 三种实现水平向滑动方式(ViewPager、ViewFilpper、ViewFlow)的比较
- android 三种实现水平向滑动方式(ViewPager、ViewFilpper、ViewFlow)的比较
- android 三种实现水平向滑动方式(ViewPager、ViewFilpper、ViewFlow)的比较
- android中三种方式实现水平滑动ViewPager,ViewFilpper,ViewFlow
- android中三种方式实现水平滑动ViewPager,ViewFilpper,ViewFlow
- android scrollView 内嵌ViewPager或Gallery等水平滑动控件冲突问题解决实现同时滑动