Android学习之——ViewPager及应用引导页的开发
背景知识
当我们第一次安装Android应用时,有的应用会有引导页,要么是用于介绍应用的新功能,要么就是关于应用的介绍,有的甚至是推广广告等。
那么这个应用引导页是怎样实现的呢?这就得有请我们今天的主角登场了——ViewPager。
ViewPager介绍
ViewPager继承自ViewGroup类,属于android.support.v4.view包(这个包是Google提供给我们开发兼容低版本Android的包,主要功能是提供各种各样的类来向后处理View的兼容性)。
ViewPager,允许用户左右滑动来查看View。和ListView一样,不能直接将View对象呈现在ViewPager上。需实现PagerAdapter来将View适配成Page以显示到ViewPager上。ViewPager经常和Fragment同时使用,这是一种使用Page和管理Page生命周期很方便的方式。
如何使用ViewPager
1.在布局文件中添加ViewPager(注意要写android.support.v4.view.ViewPager)
1 <android.support.v4.view.ViewPager 2 android:id="@+id/viewpager" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" > 5 </android.support.v4.view.ViewPager>
2.加载要显示的Page
1 private List<View> views; 2 3 LayoutInflater inflater = LayoutInflater.from(this); 4 view1 = inflater.inflate(R.layout.one, null); 5 view2 = inflater.inflate(R.layout.two, null); 6 view3 = inflater.inflate(R.layout.three, null); 7 views = new ArrayList<View>(); 8 views.add(view1); 9 views.add(view2); 10 views.add(view3);
3.实例化ViewPager并设置它的Adapter。
方法1:直接在Activity中重写PagerAdapter
1 PagerAdapter pagerAdapter = new PagerAdapter() { 2 3 @Override 4 public boolean isViewFromObject(View arg0, Object arg1) { 5 6 return arg0 == arg1; 7 } 8 9 @Override 10 public int getCount() { 11 12 return views.size(); 13 } 14 15 @Override 16 public void destroyItem(ViewGroup container, int position, 17 Object object) { 18 container.removeView(views.get(position)); 19 20 } 21 22 @Override 23 public int getItemPosition(Object object) { 24 25 return super.getItemPosition(object); 26 } 27 28 @Override 29 public CharSequence getPageTitle(int position) { 30 31 return titleList.get(position); 32 } 33 34 @Override 35 public Object instantiateItem(ViewGroup container, int position) { 36 container.addView(views.get(position)); 37 return viewList.get(position); 38 } 39 40 }; 41 viewPager.setAdapter(pagerAdapter);
方法2.创建自己的PagerAdapter类继承自PagerAdapter类。
1 public class ViewPagerAdapter extends PagerAdapter { 2 3 private List<View> views; 4 private Context context; 5 6 /** 7 * 构造方法 8 * @param views 9 * @param context 10 */ 11 public ViewPagerAdapter(List<View> views, Context context) { 12 13 this.views = views; 14 this.context = context; 15 } 16 /** 17 * 销毁View 18 */ 19 @Override 20 public void destroyItem(View container, int position, Object object) { 21 22 ((ViewPager) container).removeView(views.get(position)); 23 } 24 /** 25 * 实例化View 26 */ 27 @Override 28 public Object instantiateItem(View container, int position) { 29 30 ((ViewPager) container).addView(views.get(position)); 31 32 return views.get(position); 33 34 } 35 36 @Override 37 public int getCount() { 38 return views.size(); 39 } 40 41 @Override 42 public boolean isViewFromObject(View arg0, Object arg1) { 43 return (arg0 == arg1); 44 } 45 46 }
实现一个PagerAdapter,要实现以下几种方法:
instantiateItem(ViewGroup, int) //实例化 destroyItem(ViewGroup, int, Object) //销毁 getCount() //获取总数 isViewFromObject(View, Object) //用于确认instantiateItem是否返回了和关键对象有关的Page视图
效果展示:
使用ViewPager开发应用引导页
学会了使用ViewPager之后,开发应用引导页就没有什么难点了。关键就是:用户只有在第一次安装应用进入应用后才会有引导页,之后打开就直接进入主界面了。
所以这里要有一个判断:用户是不是第一次进入应用。将这个值存储在手机中,在这里使用SharedPreferences存储。
1 //用SharedPreferences来存储用户是否是安装后第一次使用的值 2 SharedPreferences perPreferences = getSharedPreferences("JohnTsai", MODE_PRIVATE); 3 isFirstUse = perPreferences.getBoolean("isFirstUse", true); 4 if (!isFirstUse) { 5 //进入主界面 6 ... 7 }else{ 8 //反之则跳转到引导界面 9 ... 10 Editor editor = perPreferences.edit(); 11 editor.putBoolean("isFirstUse", false); 12 editor.commit(); 13 }
注意到每个引导页页面下方都有1个小黑点,用于指示当前所在页。
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" > 5 6 <android.support.v4.view.ViewPager 7 android:id="@+id/viewpager" 8 android:layout_width="fill_parent" 9 android:layout_height="fill_parent" 10 android:background="#00000000" > 11 </android.support.v4.view.ViewPager> 12 13 <LinearLayout 14 android:id="@+id/linearLayout" 15 android:layout_width="fill_parent" 16 android:layout_height="wrap_content" 17 android:layout_alignParentBottom="true" 18 android:gravity="center_horizontal" 19 android:orientation="horizontal" > 20 21 <!-- 图片下方的点 --> 22 <ImageView 23 android:id="@+id/imageView1" 24 android:layout_width="wrap_content" 25 android:layout_height="wrap_content" 26 android:src="@drawable/point_selected" /> 27 28 <ImageView 29 android:id="@+id/imageView2" 30 android:layout_width="wrap_content" 31 android:layout_height="wrap_content" 32 android:src="@drawable/point_unselected" /> 33 34 <ImageView 35 android:id="@+id/imageView3" 36 android:layout_width="wrap_content" 37 android:layout_height="wrap_content" 38 android:src="@drawable/point_unselected" /> 39 </LinearLayout> 40 41 </RelativeLayout>
那怎样实现滑动,图片下方的点也随着改变呢?这就要实现OnPageChangeListener接口了,重写它的方法。
1 //引导界面下面的小点,用于显示当前View是第几个 2 private ImageView[] dots; 3 private int[] ids = { R.id.imageView1, R.id.imageView2,R.id.imageView3 }; 4 dots = new ImageView[views.size()]; 5 for (int i = 0; i < views.size(); i++) { 6 dots[i] = (ImageView) findViewById(ids[i]); 7 } 8 @Override 9 public void onPageScrollStateChanged(int arg0) { 10 11 } 12 13 @Override 14 public void onPageScrolled(int arg0, float arg1, int arg2) { 15 16 } 17 18 @Override 19 public void onPageSelected(int arg0) { 20 for (int i = 0; i < ids.length; i++) { 21 //若当前的界面是用户选中的界面,则点设置为选中状态,反之,则为没选中状态 22 if (arg0 == i) { 23 dots[i].setImageResource(R.drawable.point_selected); 24 } else { 25 dots[i].setImageResource(R.drawable.point_unselected); 26 } 27 } 28 }
效果展示:
要实现应用引导页面,现在只需再创建两个Activity:一个是欢迎界面(WelcomeActivity)另一个则是应用主界面 (MainActivity)
WelcomeActivity代码:
1 public class WelcomeActivity extends Activity { 2 3 //判断用户是否是第一次使用该应用 4 private boolean isFirstUse = false; 5 //延时时间,用于由欢迎界面进入另外的页面的延时效果 6 private static final int TIME = 2*1000; 7 private static final int TO_MAIN = 100001; 8 private static final int TO_GUIDE = 100002; 9 10 11 @Override 12 protected void onCreate(Bundle savedInstanceState) { 13 super.onCreate(savedInstanceState); 14 setContentView(R.layout.welcome); 15 init(); 16 } 17 //由于不能在主线程中直接延时,所以用一个Handler来处理发送过来的消息 18 Handler myHandler = new Handler(){ 19 public void handleMessage(android.os.Message msg) { 20 switch (msg.what) { 21 case TO_MAIN: 22 Intent i1 = new Intent(WelcomeActivity.this,MainActivity.class); 23 startActivity(i1); 24 finish(); 25 break; 26 case TO_GUIDE: 27 Intent i2 = new Intent(WelcomeActivity.this,GuideActivity.class); 28 startActivity(i2); 29 finish(); 30 break; 31 } 32 }; 33 }; 34 35 36 private void init() { 37 //将用户是否是第一次使用的值用SharedPreferences存储到本地 38 SharedPreferences perPreferences = getSharedPreferences("JohnTsai", MODE_PRIVATE); 39 isFirstUse = perPreferences.getBoolean("isFirstUse", true); 40 if (!isFirstUse) { 41 myHandler.sendEmptyMessageDelayed(TO_MAIN, TIME); 42 }else{ 43 myHandler.sendEmptyMessageDelayed(TO_GUIDE, TIME); 44 Editor editor = perPreferences.edit(); 45 editor.putBoolean("isFirstUse", false); 46 editor.commit(); 47 } 48 49 }
MainActivity代码很简单,只需要改写下它所对应的布局文件就好了。
应用引导界面Demo展示: