如何使 ViewPager2 看起来像一个带有 'slide' 页面转换器的无限循环?
How to make ViewPager2 look like an infinite loop with a 'slide' page transformer?
我正在寻找一个无限循环来在 ViewPager2 中显示图片。
在图片之间,以及最后一项和第一项,以及第一项和最后一项之间,使用 'slide' 页面转换器(我认为是默认设置)。
我发现的难度是:
- 没有
Integer.maxValue
项,
- 在第一个元素和最后一个元素之间有一个真正的过渡,而不是
setCurrentItem(x, false)
这不太好看。
我找到了一个解决方案:列表中有两个假项目(第一个和最后一个元素),当我们从第二个滚动到最后一个时,我们更改为第 n-2 个项目(-> 真实项目的最后一个)。但问题是过渡不好。
所以我想象一个更适合我的情况的解决方案:复制最后两个项目并将它们放在数组的开头。
- 前面的列表:[A、B、C、D、E、F]
- 转换后列表:[E', F', A, B, C, D, E, F]
思路是先显示item A(位置2),滚动到item F(位置n-1)时强制显示item F'(位置1)。当我们滚动到项目 E'(位置 0)时,我们强制显示项目 E(位置 n-2).
所以,无论什么位置,我们总是有一个项目在左边,一个项目在右边,我们总是可以用漂亮的页面转换器滚动。
限制是至少有两个项目。当然我们不必只滚动一个项目。
Java代码:
public class MyPagerActivity extends Activity {
private ViewPager2 pager;
private final MyPagerAdapter adapter = new MyPagerAdapter();
private ViewPager2.OnPageChangeCallback pageChangeCallback = new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(final int position) {
super.onPageSelected(position);
currentPosition = position;
onFocusChange();
}
@Override
public void onPageScrollStateChanged(final int state) {
super.onPageScrollStateChanged(state);
if (state == ViewPager2.SCROLL_STATE_IDLE) {
if (currentPosition == 0) {
pager.setCurrentItem(fakeSize - 2, false);
} else if (currentPosition == fakeSize - 1) {
pager.setCurrentItem(1, false);
}
} else if (state == ViewPager2.SCROLL_STATE_DRAGGING && currentPosition == fakeSize) {
//we scroll too fast and miss the state SCROLL_STATE_IDLE for the previous item
pager.setCurrentItem(2, false);
}
}
};
private ArrayList<String> itemList;
private int fakeSize;
private int realSize;
private int currentPosition;
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.pager = findViewById(R.id.mypager_viewpager);
this.pager.setAdapter(this.adapter);
this.pager.registerOnPageChangeCallback(this.pageChangeCallback);
this.pager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
final ArrayList<String> itemList = null;//your data
this.realSize = itemList.size();
this.fakeSize = this.realSize + 2;
this.itemList = transformListAndAddTwo(itemList);
this.adapter.*updateList*(this.itemList);
final int item = 2; //number two because we have two elements before the chosen one
this.pager.setCurrentItem(item, false);
}
private void onFocusChange() {
//Do something
}
/**
* add two lasts item at beginning on the new array
* @param itemList
* @return
*/
public static ArrayList<String> transformListAndAddTwo(final ArrayList<String> itemList) {
final int size = itemList.size();
final ArrayList<String> listTemp = new ArrayList<>(size + 2);
for (int iPL = 0; iPL <= size + 2; iPL++) {
listTemp.add(itemList.get((iPL + size - 2) % size));
}
return listTemp;
}
}
我正在寻找一个无限循环来在 ViewPager2 中显示图片。
在图片之间,以及最后一项和第一项,以及第一项和最后一项之间,使用 'slide' 页面转换器(我认为是默认设置)。
我发现的难度是:
- 没有
Integer.maxValue
项, - 在第一个元素和最后一个元素之间有一个真正的过渡,而不是
setCurrentItem(x, false)
这不太好看。
我找到了一个解决方案:列表中有两个假项目(第一个和最后一个元素),当我们从第二个滚动到最后一个时,我们更改为第 n-2 个项目(-> 真实项目的最后一个)。但问题是过渡不好。
所以我想象一个更适合我的情况的解决方案:复制最后两个项目并将它们放在数组的开头。
- 前面的列表:[A、B、C、D、E、F]
- 转换后列表:[E', F', A, B, C, D, E, F]
思路是先显示item A(位置2),滚动到item F(位置n-1)时强制显示item F'(位置1)。当我们滚动到项目 E'(位置 0)时,我们强制显示项目 E(位置 n-2).
所以,无论什么位置,我们总是有一个项目在左边,一个项目在右边,我们总是可以用漂亮的页面转换器滚动。
限制是至少有两个项目。当然我们不必只滚动一个项目。
Java代码:
public class MyPagerActivity extends Activity {
private ViewPager2 pager;
private final MyPagerAdapter adapter = new MyPagerAdapter();
private ViewPager2.OnPageChangeCallback pageChangeCallback = new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(final int position) {
super.onPageSelected(position);
currentPosition = position;
onFocusChange();
}
@Override
public void onPageScrollStateChanged(final int state) {
super.onPageScrollStateChanged(state);
if (state == ViewPager2.SCROLL_STATE_IDLE) {
if (currentPosition == 0) {
pager.setCurrentItem(fakeSize - 2, false);
} else if (currentPosition == fakeSize - 1) {
pager.setCurrentItem(1, false);
}
} else if (state == ViewPager2.SCROLL_STATE_DRAGGING && currentPosition == fakeSize) {
//we scroll too fast and miss the state SCROLL_STATE_IDLE for the previous item
pager.setCurrentItem(2, false);
}
}
};
private ArrayList<String> itemList;
private int fakeSize;
private int realSize;
private int currentPosition;
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.pager = findViewById(R.id.mypager_viewpager);
this.pager.setAdapter(this.adapter);
this.pager.registerOnPageChangeCallback(this.pageChangeCallback);
this.pager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
final ArrayList<String> itemList = null;//your data
this.realSize = itemList.size();
this.fakeSize = this.realSize + 2;
this.itemList = transformListAndAddTwo(itemList);
this.adapter.*updateList*(this.itemList);
final int item = 2; //number two because we have two elements before the chosen one
this.pager.setCurrentItem(item, false);
}
private void onFocusChange() {
//Do something
}
/**
* add two lasts item at beginning on the new array
* @param itemList
* @return
*/
public static ArrayList<String> transformListAndAddTwo(final ArrayList<String> itemList) {
final int size = itemList.size();
final ArrayList<String> listTemp = new ArrayList<>(size + 2);
for (int iPL = 0; iPL <= size + 2; iPL++) {
listTemp.add(itemList.get((iPL + size - 2) % size));
}
return listTemp;
}
}