使用ViewPager实现左右滑动效果

来源:互联网 发布:用邮箱怎么注册淘宝账号 编辑:程序博客网 时间:2024/05/14 23:35

使用ViewPager实现左右滑动效果

热度 10已有 439 次阅读 2012-5-29 14:20 |系统分类:Android| ViewPager, 滑动效果

        上部分中,我们已经讲解了通过系统提供的ViewFlipper来实现简单的图片滑动的效果。在这部分中,我们来讲解更加复杂的滑动界面是怎么实现的。
 
        在这部分的讲解中,我们使用了Android提供另一个非常有用的控件ViewPager。使用这个控件,需要用到google提到的一个包——android-support-v4.jar,这个包中包含了一些非常有用的类,其中就是ViewPager类来实现页面之间的切换操作,关于android-support-v4.jar的详细信息,大家可以访问google官方网站:http://developer.android.com/sdk/compatibility-library.html。
 
        具体的把Android提供的android-support-v4.jar导入工程,并add build path的方法这里不做介绍,可以参考以上提供的网址,里面会有详细的说明,步骤比较简单。
 
        下面通过两个例子来讲解一下比较复杂的滑动界面的实现。
 
一、Demo1
 
        Demo1实现的效果是我们在浏览新闻网页时经常会看到的,屏幕的上半部分是图片,下半部分是文字的介绍,而顶部是一个导航的工具栏可以供用户选择退出或者回到主菜单等。用户通过左右的滑动屏幕,实现翻页的效果。而在屏幕的最底部,会有对当前所处页面的指示标记。
 
        主布局文件main.xml的内容如下:

[代码]xml代码:

01<?xml version="1.0" encoding="utf-8"?>
02<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
03    android:layout_width="fill_parent"
04    android:layout_height="fill_parent"
05    android:orientation="vertical" >
06     
07     <LinearLayout
08        android:layout_width="fill_parent"
09        android:layout_height="wrap_content"
10        android:orientation="vertical" >
11     <include android:id="@+id/item_header"
12          layout="@layout/item_header" />
13     <android.support.v4.view.ViewPager
14         android:id="@+id/myviewpager"
15         android:layout_width="fill_parent"
16         android:layout_height="wrap_content"/>
17     </LinearLayout>
18     
19     <LinearLayout
20        android:layout_width="fill_parent"
21        android:layout_height="fill_parent"
22        android:orientation="vertical" >
23         
24      <RelativeLayout 
25         android:layout_width="fill_parent" 
26         android:layout_height="wrap_content" 
27         android:orientation="vertical" >
28          
29       <LinearLayout 
30          android:id="@+id/mybottomviewgroup" 
31          android:layout_width="fill_parent" 
32          android:layout_height="wrap_content" 
33          android:layout_alignParentBottom="true" 
34          android:layout_marginBottom="40dp" 
35          android:gravity="center_horizontal" 
36          android:orientation="horizontal" 
37           
38       </LinearLayout
39      
40      </RelativeLayout>
41     </LinearLayout>
42      
43</FrameLayout>
       
        最外层是LinearLayout,其中包括两个Linearlayout,第一个LinearLayout是显示新闻的主界面,而第二个LinearLayout是为了在底部存放指示当前界面的标记图片。值得注意的是第一个LinearLayout中包括又包括两部分,一个是通过include引入的item_header视图,一个是ViewPager控件,在这里还要注意ViewPager空间的布局方式。代码如下:

[代码]xml代码:

01<LinearLayout
02        android:layout_width="fill_parent"
03        android:layout_height="wrap_content"
04        android:orientation="vertical" >
05     <include android:id="@+id/item_header"
06          layout="@layout/item_header" />
07     <android.support.v4.view.ViewPager
08         android:id="@+id/myviewpager"
09         android:layout_width="fill_parent"
10         android:layout_height="wrap_content"/>
11     </LinearLayout>
       
        另外,在layout文件夹下还定义了item01——item06六个布局文件作为ViewPager的六个页面,在JAVA代码中会把它们分别添加进ViewPager。Item_header.xml布局定义了屏幕上方的导航栏,通过include的方式引入了main.xml布局文件。
 
        Demo1的JAVA代码如下:

[代码]java代码:

001package com.devdiv.test.ui_test_viewpager;
002 
003import java.util.ArrayList;
004import android.app.Activity;
005import android.content.Context;
006import android.os.Bundle;
007import android.os.Parcelable;
008import android.support.v4.view.PagerAdapter;
009import android.support.v4.view.ViewPager;
010import android.support.v4.view.ViewPager.OnPageChangeListener;
011import android.view.LayoutInflater;
012import android.view.View;
013import android.view.ViewGroup;
014import android.view.ViewGroup.LayoutParams;
015import android.view.Window;
016import android.widget.ImageView;
017public class UI_Test_ViewPagerActivity extends Activity {
018  
019 private ViewPager mViewPager;
020 private ArrayList<View> mPageViews;
021 private ImageView mImageView;
022 private ImageView[] mImageViews;
023  
024 //该应用的主布局LinearLayout
025 private ViewGroup mainViewGroup;
026 //主布局底部指示当前页面的小圆点视图,LinearLayout
027 private ViewGroup indicatorViewGroup;
028  
029 //定义LayoutInflater
030 LayoutInflater mInflater;
031  
032    /** Called when the activity is first created. */
033    @Override
034    public void onCreate(Bundle savedInstanceState) {
035        super.onCreate(savedInstanceState);
036        //setContentView(R.layout.main);
037         
038        //设置窗口无标题
039        requestWindowFeature(Window.FEATURE_NO_TITLE);
040         
041        //mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
042        mInflater = getLayoutInflater();
043         
044        mPageViews = new ArrayList<View>();
045        mPageViews.add(mInflater.inflate(R.layout.item01, null));
046        mPageViews.add(mInflater.inflate(R.layout.item02, null));
047        mPageViews.add(mInflater.inflate(R.layout.item03, null));
048        mPageViews.add(mInflater.inflate(R.layout.item04, null));
049        mPageViews.add(mInflater.inflate(R.layout.item05, null));
050        mPageViews.add(mInflater.inflate(R.layout.item06, null));
051         
052        mImageViews = new ImageView[mPageViews.size()];
053         
054        mainViewGroup = (ViewGroup) mInflater.inflate(R.layout.main, null);
055         
056        mViewPager = (ViewPager) mainViewGroup.findViewById(R.id.myviewpager);
057        indicatorViewGroup = (ViewGroup) mainViewGroup.findViewById(R.id.mybottomviewgroup);
058         
059        for (int i = 0; i < mImageViews.length; i++) {
060         mImageView = new ImageView(UI_Test_ViewPagerActivity.this); 
061         mImageView.setLayoutParams(new LayoutParams(20,20)); 
062         mImageView.setPadding(200200); 
063          
064         if (i == 0) {
065          mImageView.setBackgroundResource(R.drawable.page_indicator_focused);   
066   else {
067    mImageView.setBackgroundResource(R.drawable.page_indicator);
068   }
069    
070         mImageViews[i] = mImageView;
071          
072         //把指示作用的远点图片加入底部的视图中
073         indicatorViewGroup.addView(mImageViews[i]);
074  }
075         
076        //注意这两种用法的区别,前者无法正常显示!!
077        //setContentView(R.layout.main);
078        setContentView(mainViewGroup);
079         
080         
081        mViewPager.setAdapter(new MyPagerAdapter());
082        mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
083    
084   @Override
085   public void onPageSelected(int arg0) {
086    // TODO Auto-generated method stub
087    for (int i = 0; i < mImageViews.length; i++) {
088     if(i == arg0) {
089      mImageViews[i].setBackgroundResource(R.drawable.page_indicator_focused);
090     else {
091      mImageViews[i].setBackgroundResource(R.drawable.page_indicator);
092     }
093    }
094   }
095    
096   @Override
097   public void onPageScrolled(int arg0, float arg1, int arg2) {
098    // TODO Auto-generated method stub
099     
100   }
101    
102   @Override
103   public void onPageScrollStateChanged(int arg0) {
104    // TODO Auto-generated method stub
105     
106   }
107  });
108         
109    }
110     
111    class MyPagerAdapter extends PagerAdapter {
112        @Override 
113        public int getCount() { 
114            return mPageViews.size(); 
115        
116   
117        @Override 
118        public boolean isViewFromObject(View arg0, Object arg1) { 
119            return arg0 == arg1; 
120        
121   
122        @Override 
123        public int getItemPosition(Object object) { 
124            // TODO Auto-generated method stub 
125            return super.getItemPosition(object); 
126        
127   
128        @Override 
129        public void destroyItem(View arg0, int arg1, Object arg2) { 
130            // TODO Auto-generated method stub 
131            ((ViewPager) arg0).removeView(mPageViews.get(arg1)); 
132        
133   
134        @Override 
135        public Object instantiateItem(View arg0, int arg1) { 
136            // TODO Auto-generated method stub 
137            ((ViewPager) arg0).addView(mPageViews.get(arg1)); 
138            return mPageViews.get(arg1); 
139        
140   
141        @Override 
142        public void restoreState(Parcelable arg0, ClassLoader arg1) { 
143            // TODO Auto-generated method stub 
144   
145        
146   
147        @Override 
148        public Parcelable saveState() { 
149            // TODO Auto-generated method stub 
150            return null
151        
152   
153        @Override 
154        public void startUpdate(View arg0) { 
155            // TODO Auto-generated method stub 
156   
157        
158   
159        @Override 
160        public void finishUpdate(View arg0) { 
161            // TODO Auto-generated method stub 
162   
163        }
164      
165    }
166     
167}
 
        其中,需要注意的是在自定义MyPagerAdapter继承自PagerAdapter,需要重写其中的一些重要方法,可以类比BaseAdapter的实现便于理解,具体实现参考API文档。

[代码]java代码:

01mImageViews = new ImageView[mPageViews.size()];
02         
03        mainViewGroup = (ViewGroup) mInflater.inflate(R.layout.main, null);
04         
05        mViewPager = (ViewPager) mainViewGroup.findViewById(R.id.myviewpager);
06        indicatorViewGroup = (ViewGroup) mainViewGroup.findViewById(R.id.mybottomviewgroup);
07         
08        for (int i = 0; i < mImageViews.length; i++) {
09         mImageView = new ImageView(UI_Test_ViewPagerActivity.this); 
10         mImageView.setLayoutParams(new LayoutParams(20,20)); 
11         mImageView.setPadding(200200); 
12          
13         if (i == 0) {
14          mImageView.setBackgroundResource(R.drawable.page_indicator_focused);   
15   else {
16    mImageView.setBackgroundResource(R.drawable.page_indicator);
17   }
18    
19         mImageViews[i] = mImageView;
20          
21         //把指示作用的远点图片加入底部的视图中
22         indicatorViewGroup.addView(mImageViews[i]);
23  }
 
        根据mPageViews的大小初始化ImageViews,也就是说ViewPager中存在几个Page就初始化几个圆点的图片进行相应的指示。并且根据位置,设置圆点的不同状态,出事情况下显示第一个Page,因此第一个圆点的图片是focused的状态。最后,通过indicatorViewGroup.addView(mImageViews[i])把所有圆点的图片添加到布局中,在屏幕上显示。
 
        底部圆点图片初始化并加入布局后,需要给ViewPager设置Adapter,这里使用的是我们自定义的MyPagerAdapter,然后执行setContentView操作。
 
        最后,为了是底部的圆点视图具有指示作用,需要为ViewPager设置监听器,来根据ViewPager的不同状态,改变底部圆点视图的状态。代码如下:

[代码]java代码:

01mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
02    
03   @Override
04   public void onPageSelected(int arg0) {
05    // TODO Auto-generated method stub
06    for (int i = 0; i < mImageViews.length; i++) {
07     if(i == arg0) {
08      mImageViews[i].setBackgroundResource(R.drawable.page_indicator_focused);
09     else {
10      mImageViews[i].setBackgroundResource(R.drawable.page_indicator);
11     }
12    }
13   }
14    
15   @Override
16   public void onPageScrolled(int arg0, float arg1, int arg2) {
17    // TODO Auto-generated method stub
18     
19   }
20    
21   @Override
22   public void onPageScrollStateChanged(int arg0) {
23    // TODO Auto-generated method stub
24     
25   }
26  });
27<font style="BACKGROUND-COLOR: #ffffff" face="Tahoma"></font>
 
 
        Demo1运行效果如下:
 
 
图1  Demo1运行效果1
 
 
图2  Demo1运行效果2
 
二、Demo2
       
        Demo2同样实现了左右滑动的效果,不过我们在不同的页面使用了不同的布局,这在实际的应用中也是很常见的。我们同样使用了ViewPager控件,具体方法和Demo1基本相同。
 
        不同在于,我们在两个页面中分别使用了ListView中GridView视图,并在代码中为它们分别绑定了不同的Adapter。ListView使用了简单的ArrayAdapter,显示一组数据。GridView使用了自定义的Adapter。
 
        由于Demo2和Demo1的内容非常相似,我们就不再展开分析,读者可以下载代码查看详细内容。
       
        Demo2运行效果如下:
 
 
图3  Demo2运行效果1
 
 
 
图4  Demo2运行效果2
Demo1源代码下载:UI_Test_ViewPager.rar
Demo2源代码下载:UI_Test_ViewPager3.rar
0 0