一、概述
ViewPager是android-support-v4中提供的类,它是一个容器类,常用于页面之间的切换。
本文介绍ViewPager最基础的应用:在多个View之间进行切换,亦即ViewPager的每个页面是个View。
这种模式适合每个页面的逻辑较为简单的情况,比如去实现“小红书”引导页这样的效果:
二、实现思路
2.1 页面如何布局
这个引导页一共有三个页面,毫无疑问上面的标题和配图是隶属于viewpager不同页面内部的,而下面的俩按钮则是直接放在Activity的布局中。
那indicator呢?虽然在不同的页面红点的位置不一样,但它不能放在页面的布局中,否则,三个点就会跟配图一样整体滑动了……
2.2 代码如何实现
ViewPager是什么鬼呢?其实它就是个ViewGroup,用法跟ListView类似,重点在于实现这样一个Adapter:
1 private class ViewPagerAdapter extends PagerAdapter { 2 @Override 3 public int getCount() { 4 return 0; //ViewPager总共有几个页面 5 } 6 7 @Override 8 public boolean isViewFromObject(View view, Object object) { 9 return false; //判断一个页面(View)是否与instantiateItem方法返回的Object一致 10 } 11 12 @Override 13 public Object instantiateItem(ViewGroup container, int position) { 14 return super.instantiateItem(container, position); //创建一个页面 15 } 16 17 @Override 18 public void destroyItem(ViewGroup container, int position, Object object) { 19 super.destroyItem(container, position, object); //销毁一个页面 20 } 21 }
[转载请保留本文地址:http://www.cnblogs.com/snser/p/5700751.html]
三、开始干活
3.1 摆出activity和每个页面的布局
viewpager_view.xml (activity的布局):
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:background="@drawable/viewpager_view_bg" 6 tools:context="${relativePackage}.${activityClass}" > 7 8 <android.support.v4.view.ViewPager 9 android:id="@+id/viewpager_view_pager" 10 android:layout_width="match_parent" 11 android:layout_height="match_parent" 12 android:background="@drawable/viewpager_view_bg" /> 13 14 <ImageView 15 android:id="@+id/viewpager_view_point" 16 android:layout_width="66.7dp" 17 android:layout_height="10dp" 18 android:layout_centerHorizontal="true" 19 android:layout_above="@+id/viewpager_view_register" 20 android:layout_marginBottom="20dp" 21 android:src="@drawable/viewpager_view_point_1" /> 22 23 <Button 24 android:id="@+id/viewpager_view_register" 25 android:layout_width="190dp" 26 android:layout_height="45dp" 27 android:layout_centerHorizontal="true" 28 android:layout_above="@+id/viewpager_view_login" 29 android:layout_marginBottom="10dp" 30 android:background="@drawable/viewpager_view_register_bg" 31 android:textSize="19sp" 32 android:textColor="#FFFFFF" 33 android:text="@string/viewpager_view_register" /> 34 35 <Button 36 android:id="@+id/viewpager_view_login" 37 android:layout_width="190dp" 38 android:layout_height="45dp" 39 android:layout_alignParentBottom="true" 40 android:layout_centerHorizontal="true" 41 android:layout_marginBottom="50dp" 42 android:background="@drawable/viewpager_view_login_bg" 43 android:textSize="19sp" 44 android:textColor="#999999" 45 android:text="@string/viewpager_view_login" /> 46 47 </RelativeLayout>
viewpager_view_page.xml (页面的布局):
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 tools:context="${relativePackage}.${activityClass}" > 6 7 <TextView 8 android:id="@+id/viewpager_view_page_title" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:layout_marginTop="30dp" 12 android:layout_centerHorizontal="true" 13 android:textSize="20sp" 14 android:textColor="#333333" 15 android:text="@string/viewpager_view_page_title_1" /> 16 17 <ImageView 18 android:id="@+id/viewpager_view_page_content" 19 android:visibility="visible" 20 android:layout_width="match_parent" 21 android:layout_height="385dp" 22 android:layout_marginTop="75dp" 23 android:layout_gravity="center_horizontal" 24 android:scaleType="centerInside" 25 android:src="@drawable/viewpager_view_page_content_1" /> 26 27 </RelativeLayout>
3.2 简要介绍一下即将出炉的核心代码
1 public class ViewPagerViewActivity extends Activity implements View.OnClickListener { 2 3 private ViewPager mPager; 4 private ImageView mImgPoint; 5 6 private SparseArray<View> mPageCache = new SparseArray<View>(); 7 8 @Override 9 protected void onCreate(Bundle savedInstanceState) { 10 super.onCreate(savedInstanceState); 11 setContentView(R.layout.viewpager_view); 12 initView(); 13 } 14 15 private void initView() { 16 mPager = (ViewPager)findViewById(R.id.viewpager_view_pager); 17 mImgPoint = (ImageView)findViewById(R.id.viewpager_view_point); 18 mPager.setAdapter(new ViewPagerAdapter(ViewPagerViewActivity.this)); 19 mPager.addOnPageChangeListener(new OnViewPageChangeListener()); 20 findViewById(R.id.viewpager_view_register).setOnClickListener(this); 21 findViewById(R.id.viewpager_view_login).setOnClickListener(this); 22 } 23 24 private class ViewPagerAdapter extends PagerAdapter { 25 private final int mCount = 3; 26 private LayoutInflater mInflater; 27 28 private ViewPagerAdapter(Context context) { 29 mInflater = LayoutInflater.from(context); 30 } 31 32 @Override 33 public int getCount() { 34 return mCount; 35 } 36 37 @Override 38 public boolean isViewFromObject(View view, Object obj) { 39 return view == obj; 40 } 41 42 @Override 43 public Object instantiateItem(ViewGroup container, int position) { 44 View page = mPageCache.get(position); 45 if (page == null) { 46 page = mInflater.inflate(R.layout.viewpager_view_page, container, false); 47 TextView txtTitle = (TextView)page.findViewById(R.id.viewpager_view_page_title); 48 ImageView imgContent = (ImageView)page.findViewById(R.id.viewpager_view_page_content); 49 switch (position) { 50 case 0: 51 txtTitle.setText(R.string.viewpager_view_page_title_1); 52 imgContent.setImageResource(R.drawable.viewpager_view_page_content_1); 53 break; 54 case 1: 55 txtTitle.setText(R.string.viewpager_view_page_title_2); 56 imgContent.setImageResource(R.drawable.viewpager_view_page_content_2); 57 break; 58 case 2: 59 txtTitle.setText(R.string.viewpager_view_page_title_3); 60 imgContent.setImageResource(R.drawable.viewpager_view_page_content_3); 61 break; 62 default: 63 break; 64 } 65 mPageCache.append(position, page); 66 } 67 container.addView(page); 68 return page; 69 } 70 71 @Override 72 public void destroyItem(ViewGroup container, int position, Object object) { 73 container.removeView((View)object); 74 } 75 } 76 77 private class OnViewPageChangeListener implements OnPageChangeListener { 78 @Override 79 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 80 } 81 82 @Override 83 public void onPageSelected(int position) { 84 switch (position) { 85 case 0: 86 mImgPoint.setImageResource(R.drawable.viewpager_view_point_1); 87 break; 88 case 1: 89 mImgPoint.setImageResource(R.drawable.viewpager_view_point_2); 90 break; 91 case 2: 92 mImgPoint.setImageResource(R.drawable.viewpager_view_point_3); 93 break; 94 default: 95 break; 96 } 97 } 98 99 @Override 100 public void onPageScrollStateChanged(int state) { 101 } 102 } 103 104 @Override 105 public void onClick(View v) { 106 finish(); 107 } 108 }
重点关注下 ViewPagerAdapter :
在 instantiateItem 方法中会inflate出新的页面,再根据不同的position对页面进行对应的初始化工作,同时在ViewPager中添加当前页面。
而在 destroyItem 方法中,只需要将当前页面从ViewPager中移除即可。
同时,需要给ViewPager设置一个 OnPageChangeListener ,以便在页面切换的时候更新Indicator对应的小红点位置。
3.3 关于缓存
可以看到,上面的代码在 instantiateItem 方法中用到了页面缓存,亦即每个position对应的页面只需要inflate一次。
那为什么会有缓存的需求呢?这是因为ViewPager每次加载当前页面的同时,会自动预加载(instantiateItem)与当前页面左右相隔的两个页面,同时会销毁(destroyItem)与当前页面不相邻的页面。
设想一下,滑动到第三个页面时,第一个页面会被销毁掉,而滑回第二个页面时,又会重新创建第一个页面。如果不加以缓存,就会造成页面的重复inflate从而浪费资源、降低性能。
[转载请保留本文地址:http://www.cnblogs.com/snser/p/5700751.html]
四、demo工程
保存下面的图片,扩展名改成 .zip 即可
[转载请保留本文地址:http://www.cnblogs.com/snser/p/5700751.html]