本文参考了https://www.jianshu.com/p/1ed6b41891ef
首先是布局文件
activity_main.xml:
这就是个普通的布局文件,ViewPager放在FrameLayout中,LinearLayout放在FrameLayout的底部。
在values文件夹中创建了paper_image_id.xml文件,以便后面给ViewPager的每个页面设置id,这样才能设置点击事件。
接下来是MainActivity.java
public class MainActivity extends AppCompatActivity {
public static int curposition=0;//记录当前位置
public ViewPager mViewPager;
public TextView tv;
public List mImageList;//轮播的图片集合
public String[] mImageTitles;//标题集合
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
//初始化控件
public void init(){
mViewPager=findViewById(R.id.viewpager);
tv=findViewById(R.id.tv_pager_title);
initData();//初始化数据
initView();//初始化View,设置适配器
}
//初始化数据(图片、标题、点击事件)
public void initData(){
mImageList=new ArrayList<>();
mImageTitles=new String[]{"title4","title1","title2","title3","title4","title1"};
int ImageRes[]=new int[]{R.drawable.apple_pic,R.drawable.banana_pic,R.drawable.cherry_pic,R.drawable.grape_pic};
//加入最后一张图片,以形成无限循环
ImageView iv;
iv=new ImageView(this);
iv.setBackgroundResource(ImageRes[3]);
iv.setId(R.id.pager_image1);
iv.setOnClickListener(new PagerImageOnClick());
mImageList.add(iv);
for(int i=0;i<4;i++){
iv=new ImageView(this);
iv.setBackgroundResource(ImageRes[i]);
iv.setId(R.id.pager_image1);
iv.setOnClickListener(new PagerImageOnClick());
mImageList.add(iv);
}
iv=new ImageView(this);
iv.setBackgroundResource(ImageRes[0]);
iv.setId(R.id.pager_image1);
iv.setOnClickListener(new PagerImageOnClick());
mImageList.add(iv);
}
//给ViewPager设置适配器
public void initView(){
MyViewPagerAdapter viewPagerAdapter=new MyViewPagerAdapter(mImageList,mViewPager);
mViewPager.setAdapter(viewPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
//每次切换页面都会调用这个方法
//不论是用户手动切换或者是代码导致的切换(setCurrentItem)
@Override
public void onPageSelected(int position) {
//这里的position是当前page对应的下标
curposition=position;
tv.setText(mImageTitles[position]);
}
@Override
public void onPageScrollStateChanged(int state) {
//验证当前的滑动是否结束
if(state==ViewPager.SCROLL_STATE_IDLE){
if(curposition==0){
mViewPager.setCurrentItem(4,false);//false表示不要动画效果
}else if(curposition==5){
mViewPager.setCurrentItem(1,false);
}
}
}
});
mViewPager.setCurrentItem(1);
}
private class PagerImageOnClick implements View.OnClickListener{
@Override
public void onClick(View v){
switch (v.getId()){
case R.id.pager_image1:
Toast.makeText(MainActivity.this,"图片1被点击",Toast.LENGTH_SHORT).show();
break;
case R.id.pager_image2:
Toast.makeText(MainActivity.this,"图片2被点击",Toast.LENGTH_SHORT).show();
break;
case R.id.pager_image3:
Toast.makeText(MainActivity.this,"图片3被点击",Toast.LENGTH_SHORT).show();
break;
case R.id.pager_image4:
Toast.makeText(MainActivity.this,"图片4被点击",Toast.LENGTH_SHORT).show();
break;
}
}
}
class MyViewPagerAdapter extends PagerAdapter{
private List imageViewList;
private ViewPager viewPager;
public MyViewPagerAdapter(List imageViewList,ViewPager viewPager){
this.viewPager=viewPager;
this.imageViewList=imageViewList;
}
@Override
//获取要滑动的控件的数量
//position的最大数目
public int getCount(){
return mImageList.size();
}
@Override
public boolean isViewFromObject(View view, Object object){
return view==object;
}
@Override
//一个page在切换完成后会调用该方法去加载下一个可能将被展示的page
//如page1切换到page2,则会调用该方法加载page3
//而从page3切换到page1,则会调用该方法加载page1
public Object instantiateItem(ViewGroup container,int position){
container.addView(mImageList.get(position));
return mImageList.get(position);
}
//ViewPager只会保留当前页和当前页左右两页
//如从page2滑到page3,则page1会被删除
@Override
public void destroyItem(ViewGroup container,int position,Object object){
viewPager.removeView(imageViewList.get(position));
}
}
}
这里需要一步一步看代码。
首先onCreate()调用了init()进行初始化。init()中又调用了initData()和initView()做具体的初始化操作。
在initData()中:
public void initData(){
mImageList=new ArrayList<>();
mImageTitles=new String[]{"title4","title1","title2","title3","title4","title1"};
int ImageRes[]=new int[]{R.drawable.apple_pic,R.drawable.banana_pic,R.drawable.cherry_pic,R.drawable.grape_pic};
//加入最后一张图片,以形成无限循环
ImageView iv;
iv=new ImageView(this);
iv.setBackgroundResource(ImageRes[3]);
iv.setId(R.id.pager_image1);
iv.setOnClickListener(new PagerImageOnClick());
mImageList.add(iv);
for(int i=0;i<4;i++){
iv=new ImageView(this);
iv.setBackgroundResource(ImageRes[i]);
iv.setId(R.id.pager_image1);
iv.setOnClickListener(new PagerImageOnClick());
mImageList.add(iv);
}
iv=new ImageView(this);
iv.setBackgroundResource(ImageRes[0]);
iv.setId(R.id.pager_image1);
iv.setOnClickListener(new PagerImageOnClick());
mImageList.add(iv);
}
这里的关键之处在于,原本我们想展示4张图片,并实现他们的循环播放,这里我们在图1之前加入了图4,在图4之后加入了图1。也就是说,原本我们只想展示4张图,这里的mImageList实际上却有6个ImageView。这样做的目的是,当我们从图4左滑时,我们能看到图1的部分(实际上它位于mImageList的下标5的位置),然后当我们滑动完成,下标5处的图1展示出来时,立刻切换到下标1的图1处,这样就实现了无限轮播的目的。
接下来分析initView()的代码:
//给ViewPager设置适配器
public void initView(){
MyViewPagerAdapter viewPagerAdapter=new MyViewPagerAdapter(mImageList,mViewPager);
mViewPager.setAdapter(viewPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
//每次切换页面都会调用这个方法
//不论是用户手动切换或者是代码导致的切换(setCurrentItem)
@Override
public void onPageSelected(int position) {
//这里的position是当前page对应的下标
curposition=position;
tv.setText(mImageTitles[position]);
}
@Override
public void onPageScrollStateChanged(int state) {
//验证当前的滑动是否结束
if(state==ViewPager.SCROLL_STATE_IDLE){
if(curposition==0){
mViewPager.setCurrentItem(4,false);//false表示不要动画效果
}else if(curposition==5){
mViewPager.setCurrentItem(1,false);
}
}
}
});
mViewPager.setCurrentItem(1);
}
分析initView()的代码之前先看看自定义的ViewPager适配器的代码
class MyViewPagerAdapter extends PagerAdapter{
private List imageViewList;
private ViewPager viewPager;
public MyViewPagerAdapter(List imageViewList,ViewPager viewPager){
this.viewPager=viewPager;
this.imageViewList=imageViewList;
}
@Override
//获取要滑动的控件的数量
//position的最大数目
public int getCount(){
return mImageList.size();
}
@Override
public boolean isViewFromObject(View view, Object object){
return view==object;
}
@Override
//一个page在切换完成后会调用该方法去加载下一个可能将被展示的page
//如page1切换到page2,则会调用该方法加载page3
//而从page3切换到page2,则会调用该方法加载page1
public Object instantiateItem(ViewGroup container,int position){
container.addView(mImageList.get(position));
return mImageList.get(position);
}
//ViewPager只会保留当前页和当前页左右两页
//如从page2滑到page3,则page1会被删除
@Override
public void destroyItem(ViewGroup container,int position,Object object){
viewPager.removeView(imageViewList.get(position));
}
}
这就是个简单的ViewPager适配器。
instantiateItem()方法在一个page切换完成时会被调用,加载下一个可能被展示的page。如我从page1切换到page2,那么instantiateItem()方法会加载page3;而从page3切换到page2,则会加载page1;
destroyItem()方法的调用,ViewPager值会保留当前页和当前页的左右两页。如果从page2切换到page3,则page1会被删除,因为page3的左右时page2和page4.
看完了适配器后再看看initView().
initView()主要的工作就是为viewPager设置一个适配器。设置完适配器之后又给ViewPager设置了翻页的响应事件。
这里重写了onPageSelected()和onPageScrollStateChanged()
每次页面的切换完成,onPageSelected()方法就会被调用。不论是用户滑动页面导致的页面切换还是代码setCutrrentItem()导致的页面切换,都会调用这个方法。这里我们获取了当前页面的下标。
**而onPageScrollStateChanged()在滑动状态发生改变时会被调用。例如:从静止到突然有滑动发生时,会调用;从滑动状态突然停下来(未切换页面)也会调用;从滑动状态到滑动完成(成功切换页面)也会调用。在这里当滑动结束时,如果当前下标是5,即从图4滑动到下标5的图1时,就应该切换到下标1的图1且不应该有切换的动画效果。**下标为0时同理切换到下标4的图4