- ViewPager是一个页面切换组件,可以往里面添加多个View
- 需要一个适配器(Adapter)把多个View和Viewpager绑定(PageAdapter、FragmentAdapter、FragmentStateAdapter)
PageAdapter和FragmentAdapter会缓存左边,当前,右边的三个页面,当处于最左边则只缓存当前和右边两个页面
当有4个页面:
若当前处于页面1,则会缓存1,2
若当前处于页面2,则会缓存1,2,3
适用页面少的情况下。 - FragmentStateAdapter:只保存Fragment的状态,当对用户不可见时,Fragment被销毁。显示时则重新生成页面。适用页面多的情况下。
实现Runnable和继承Thread的区别
1. PagerAdapter的使用
重写的方法:
1.getCount():获得viewpager中有多少个view
2.destroyItem():移除一个给定位置的页面。
3.instantiateItem(): ①将给定位置的view添加到ViewGroup(容器)中,创建并显示出来 ②返回一个代表新增页面的Object(key),通常都是直接返回view本身就可以了,当然你也可以 自定义自己的key,但是key和每个view要一一对应的关系.( 渲染页面的函数)
4.isViewFromObject(): 判断instantiateItem(ViewGroup, int)函数所返回来的Key与一个页面视图是否是 代表的同一个视图(即它俩是否是对应的,对应的表示同一个View),通常我们直接写 return view == object!
例子:
图片资源
public class Images {
public static final int[] imageArrays=new int[]{R.drawable.bg1,R.drawable.bg2,R.drawable.bg3,
R.drawable.bg4};
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
</RelativeLayout>
子项View:viewpager_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv"
android:layout_height="match_parent"
android:layout_width="match_parent" />
</RelativeLayout>
自定义适配器
public class ViewPagerAdapter extends PagerAdapter {
private Context context;
private int[] datas;//图片资源
private LayoutInflater layoutInflater;//布局加载器
public ViewPagerAdapter(Context context,int[] datas){
super();
this.context=context;
this.datas=datas;
layoutInflater=LayoutInflater.from(context);
}
//ViewPager中View的个数
@Override
public int getCount() {
return datas.length;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
//移除Item
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
//渲染每一页数据
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view=layoutInflater.inflate(R.layout.viewpager_item,null);//加载子项View
ImageView iv= (ImageView) view.findViewById(R.id.iv);//获取子项View的子控件
iv.setImageResource(datas[position]);//设置显示图片
container.addView(view);//添加到ViewPager
return view;
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private ViewPager vp;
ViewPagerAdapter viewPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vp= (ViewPager) findViewById(R.id.vp);
viewPagerAdapter=new ViewPagerAdapter(this,Images.imageArrays);
vp.setAdapter(viewPagerAdapter);//为ViewPager添加适配器
}
}
在渲染页面里还可以通过异步任务来实现
public class BitmapTask extends AsyncTask<Integer,Void,Bitmap> {
private int res;
private Context context;
private ImageView iv;
public BitmapTask(ImageView iv, Context context) {
this.iv = iv;
this.context = context;
}
@Override
protected Bitmap doInBackground(Integer... params) {
res=params[0];
Bitmap bitmap= BitmapFactory.decodeResource(context.getResources(),res);
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
iv.setImageBitmap(bitmap);
}
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view=layoutInflater.inflate(R.layout.viewpager_item,null);//加载子项View
ImageView iv= (ImageView) view.findViewById(R.id.iv);//获取子项View的子控件
//iv.setImageResource(datas[position]);//设置显示图片
BitmapTask bitmapTask=new BitmapTask(iv,context);
bitmapTask.execute(datas[position]);
container.addView(view);//添加到ViewPager
return view;
}
实现轮播:上述切换只能切换到第四张,就不能再往右翻了。
第一种方式:欺骗适配器
修改如下
@Override
public int getCount() {
return Integer.MAX_VALUE;
//return datas.length;
}
另外对position取余:position%datas.length
bitmapTask.execute(datas[position%datas.length]);
但上述只能右翻,不能左翻,因为一开始是处于第0项,所以要设置初始显示的页面
在MainActivity中增加
vp.setCurrentItem(4*1000,true);//4表示的一共有4张照片轮播,这样左翻才能翻到第四张,true表示快速定位
所以综上,左翻和右翻都是有一定次数限定的。
第二种方式:构造数据源 :0-1-2-3 -》3-0-1-2-3-0,构造后的数据比原来的数据源多增加2个,当跳转到最后一个0时,把它切换到第一个0,对于3同理。
主要修改了MainActivity,还有ViewPagerAdapter也要修改回来
public class MainActivity extends AppCompatActivity {
private ViewPager vp;
ViewPagerAdapter viewPagerAdapter;
private int[] datas=new int[Images.imageArrays.length+2];//比原来的数据多了2
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
vp= (ViewPager) findViewById(R.id.vp);
viewPagerAdapter=new ViewPagerAdapter(this,datas);
vp.setAdapter(viewPagerAdapter);
vp.addOnPageChangeListener(new ViewPagerChandeListener());
vp.setCurrentItem(1,true);
}
//增加了该函数
private void initData() {
datas[0]=Images.imageArrays[Images.imageArrays.length-1];
for(int i=0;i<Images.imageArrays.length;i++){
datas[i+1]=Images.imageArrays[i];
}
datas[datas.length-1]=Images.imageArrays[0];
}
//增加了该ViewPager的监听
class ViewPagerChandeListener implements ViewPager.OnPageChangeListener{
@Override
public void onPageSelected(int position) {
if(position==0){
vp.setCurrentItem(datas.length-2,true);
}else if(position==datas.length-1){
vp.setCurrentItem(1,true);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
}
实现自动轮播
修改MainActivity
public class MainActivity extends AppCompatActivity {
private ViewPager vp;
ViewPagerAdapter viewPagerAdapter;
private int[] datas=new int[Images.imageArrays.length+2];
//增加了这
private ScheduledExecutorService scheduledExecutorService;
private int CurrentIndex;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
vp= (ViewPager) findViewById(R.id.vp);
viewPagerAdapter=new ViewPagerAdapter(this,datas);
vp.setAdapter(viewPagerAdapter);
vp.addOnPageChangeListener(new ViewPagerChandeListener());
//增加了这
CurrentIndex=1;
vp.setCurrentItem(1,true);
}
//增加了这以下
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 1:
vp.setCurrentItem(CurrentIndex);
break;
}
}
};
@Override
protected void onStart() {
super.onStart();
scheduledExecutorService= Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
CurrentIndex++;
handler.sendEmptyMessage(1);
}
},10,10, TimeUnit.SECONDS);
}
@Override
protected void onStop() {
super.onStop();
if(scheduledExecutorService!=null)
scheduledExecutorService.shutdown();
}
private void initData() {
datas[0]=Images.imageArrays[Images.imageArrays.length-1];
for(int i=0;i<Images.imageArrays.length;i++){
datas[i+1]=Images.imageArrays[i];
}
datas[datas.length-1]=Images.imageArrays[0];
}
private class ViewPagerChandeListener implements ViewPager.OnPageChangeListener{
@Override
public void onPageSelected(int position) {
//增加了这
CurrentIndex=position;
if(position==0){
vp.setCurrentItem(datas.length-2,true);
}else if(position==datas.length-1){
vp.setCurrentItem(1,true);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
}