目前看到的大部分教程都是ViewPager+Fragment实现的无限滑动效果,比较复杂。ViewPager2的出现给我们带来的极大的方便,要实现无限滑动效果也相对简单一些了。
实现无限滑动的原理和ViewPager的原理是一样的,相关原理可以借鉴。假设我们要对三个页面进行滑动,分别为fragment1,fragment2,fragment3,。我们就按顺序导入fragment3,fragment1,fragment2,fragment3,fragment1。
当页面跳转到第0个页面,也就是fragment3的时候,我们将页面自动改为第3个页面,fragment3。当页面跳转到第4个页面,也就是fragment1的时候,我们将页面自动改为第1个页面,fragment1。
//MyAdapter.java
public class MyAdapter extends FragmentStateAdapter {
List<Fragment> list = new ArrayList<>();
public EmergentAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle, List<Fragment> list){
super(fragmentManager,lifecycle);
this.list = list;
}
@NonNull
@Override
public Fragment createFragment(int position) {
return list.get(position);
}
@Override
public int getItemCount() {
return list.size();
}
}
public class EmergentActivity extends AppCompatActivity{
private int imgsize=5;
private ViewPager2 viewPager2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_emergent);
List<Fragment> list=new ArrayList<>();
list.add(0,new BlankFragment3());//fragment末尾
list.add(1,new BlankFragment1());//fragment1
list.add(2,new BlankFragment2());//fragment2
list.add(3,new BlankFragment3());//fragment3
list.add(4,new BlankFragment1());//fragment开头
viewPager2 =findViewById(R.id.viewpager);
viewPager2.setAdapter(new MyAdapter(getSupportFragmentManager(),getLifecycle(),list));
viewPager2.setCurrentItem(imgsize/2);//设置默认的页面为中心页面
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback(){
@Override
public void onPageSelected(int position){//无动画跳转 最后一个fragment跳转到fragment1,第0个fragment跳转到fragment_size-1
if(position==0){
viewPager2.setCurrentItem(imgsize-2,false);
}
if(position==imgsize-1){
viewPager2.setCurrentItem(1,false);
}
}
});
}
}
使用ViewPager2+Fragment实现无限滑动的代码量比ViewPager+Fragment确实少了很多。但是这个效果仍然有一个小问题:onPageSelected事件是做完选择之后,而我们实际做完选择之后,仍有一部分的滑动动画。而我们在这个时间点进行setCurrentItem,就会导致后面一部分动画消失。也就是说,在进行首尾的交替的时候,动画会比一般的Fragment交替快一点。
更新:解决了如上问题:(添加了一个新的监听和一个存储选择的变量,在选择完毕后,存储该选择,在动画结束后,根据存储的选择更改fragment,这个方法的坏处是在翻页太快时,会在首尾fragment切换时卡一下,不过影响并不大)
public class EmergentActivity extends AppCompatActivity{
private final int imgsize=5;
private int CurrentPos;
private ViewPager2 viewPager2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_emergent);
CurrentPos = imgsize/2;
List<Fragment> list=new ArrayList<>();
list.add(0,new BlankFragment3());//fragment末尾
list.add(1,new BlankFragment1());//fragment1
list.add(2,new BlankFragment2());//fragment2
list.add(3,new BlankFragment3());//fragment3
list.add(4,new BlankFragment1());//fragment开头
viewPager2 =findViewById(R.id.viewpager);
viewPager2.setAdapter(new EmergentAdapter(getSupportFragmentManager(),getLifecycle(),list));
viewPager2.setCurrentItem(imgsize/2);//设置默认的页面为中心页面
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback(){
@Override
public void onPageSelected(int position){
CurrentPos=position;
}
@Override
public void onPageScrollStateChanged(int arg0){
if(arg0==0){//表示滑动结束了
if(CurrentPos==0){//无动画跳转 最后一个fragment跳转到fragment1,第0个fragment跳转到fragment_size-1
viewPager2.setCurrentItem(imgsize-2,false);
}
if(CurrentPos==imgsize-1){
viewPager2.setCurrentItem(1,false);
}
}
}
});
}
}
相关的系统性内容可以学习一下这个博客内容: