使用 FragmentStatePagerAdapter 从 ViewPager 中动态删除一个项目
Dynamically remove an item from a ViewPager with FragmentStatePagerAdapter
围绕这个话题有不少讨论
- ViewPager PagerAdapter not updating the View
- Update ViewPager dynamically?
- Removing fragments from FragmentStatePagerAdapter
我尝试了各种解决方案(包括 POSITION_NONE
的失效)
.但我仍然不知道如何正确删除项目。
发生的事情是
- 要么我得到一个空白页(意味着片段被破坏,但是
instantiateItem
没有要求更换)
- 或者整个系统崩溃可能是因为 Android 管理
片段实例与我保存它们的方式不匹配
arraylist/sparsearray
这是我的适配器
private class DatePickerPagerAdapter extends FragmentStatePagerAdapter {
ArrayList<Fragment> registeredFragments = new ArrayList<Fragment>();
public DatePickerPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return CreateWishFormDatePaginationFragment.newInstance(position);
}
@Override
public int getItemPosition(Object object){ //doesnt change much..
return PagerAdapter.POSITION_NONE;
}
@Override
public int getCount() {
return iPageCount;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.add(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, registeredFragments.get(position));
}
public void removePage(ViewGroup pager, int position) {
destroyItem(pager, position, null);
registeredFragments.remove(position);
iPageCount--;
pagerIndicator.notifyDataSetChanged();
pagerAdapter.notifyDataSetChanged();
}
public void addPage() {
iPageCount++;
pagerIndicator.notifyDataSetChanged();
pagerAdapter.notifyDataSetChanged();
}
}
我正在使用带有 ViewPagerIndicator 的视图寻呼机,我希望能够删除中间的一个页面,例如。
因此问题仍然存在,在 ViewPager 中处理添加和删除片段的正确方法是什么?
谢谢!
如果您想从 ViewPager
中删除项目,以下代码没有意义:
@Override
public Fragment getItem(int position) {
return CreateWishFormDatePaginationFragment.newInstance(position);
}
本质上,您在 position
的基础上创建了一个 Fragment
。无论删除哪个页面,position
的范围都会从 [0, iPageCount
) 变为 [0, iPageCount-1
),意思就是永远去掉最后的Fragment
。
你需要的大致如下:
public class DatePickerPagerAdapter extends FragmentStatePagerAdapter
{
private ArrayList<Integer> pageIndexes;
public DatePickerPagerAdapter(FragmentManager fm) {
super(fm);
pageIndexes = new ArrayList<>();
for (int i = 0; i < 10; i++) {
pageIndexes.add(new Integer(i));
}
}
@Override
public int getCount() {
return pageIndexes.size();
}
@Override
public Fragment getItem(int position) {
Integer index = pageIndexes.get(position);
return CreateWishFormDatePaginationFragment.newInstance(index.intValue());
}
// This is called when notifyDataSetChanged() is called
@Override
public int getItemPosition(Object object) {
// refresh all fragments when data set changed
return PagerAdapter.POSITION_NONE;
}
// Delete a page at a `position`
public void deletePage(int position)
{
// Remove the corresponding item in the data set
pageIndexes.remove(position);
// Notify the adapter that the data set is changed
notifyDataSetChanged();
}
}
有关从 FragmentStatePagerAdapter 中删除项目的更多详细信息,请参阅完整的 example。
ViewPager 不会使用上面的代码删除您的片段,因为它会将多个视图(或片段)加载到内存中。除了可见视图之外,它还将视图加载到可见视图的任一侧。这提供了从一个视图到另一个视图的平滑滚动,这使得 ViewPager 非常酷。
要达到您想要的效果,您需要做几件事。
- 将 FragmentPagerAdapter 更改为 FragmentStatePagerAdapter。这样做的原因是 FragmentPagerAdapter 将永远保留它加载到内存中的所有视图。 FragmentStatePagerAdapter 处理当前视图和可遍历视图之外的视图的位置。
覆盖适配器方法 getItemPosition(如下所示)。当我们调用 mAdapter.notifyDataSetChanged(); ViewPager 询问适配器以确定在定位方面发生了什么变化。我们使用此方法表示一切都已更改,因此重新处理所有视图定位。
这是代码...
private class MyPagerAdapter extends FragmentStatePagerAdapter {
//... your existing code
@Override
public int getItemPosition(Object object){
return PagerAdapter.POSITION_NONE;
}
}
围绕这个话题有不少讨论
- ViewPager PagerAdapter not updating the View
- Update ViewPager dynamically?
- Removing fragments from FragmentStatePagerAdapter
我尝试了各种解决方案(包括 POSITION_NONE
的失效)
.但我仍然不知道如何正确删除项目。
发生的事情是
- 要么我得到一个空白页(意味着片段被破坏,但是
instantiateItem
没有要求更换) - 或者整个系统崩溃可能是因为 Android 管理
片段实例与我保存它们的方式不匹配
arraylist/sparsearray
这是我的适配器
private class DatePickerPagerAdapter extends FragmentStatePagerAdapter {
ArrayList<Fragment> registeredFragments = new ArrayList<Fragment>();
public DatePickerPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return CreateWishFormDatePaginationFragment.newInstance(position);
}
@Override
public int getItemPosition(Object object){ //doesnt change much..
return PagerAdapter.POSITION_NONE;
}
@Override
public int getCount() {
return iPageCount;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.add(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, registeredFragments.get(position));
}
public void removePage(ViewGroup pager, int position) {
destroyItem(pager, position, null);
registeredFragments.remove(position);
iPageCount--;
pagerIndicator.notifyDataSetChanged();
pagerAdapter.notifyDataSetChanged();
}
public void addPage() {
iPageCount++;
pagerIndicator.notifyDataSetChanged();
pagerAdapter.notifyDataSetChanged();
}
}
我正在使用带有 ViewPagerIndicator 的视图寻呼机,我希望能够删除中间的一个页面,例如。
因此问题仍然存在,在 ViewPager 中处理添加和删除片段的正确方法是什么?
谢谢!
如果您想从 ViewPager
中删除项目,以下代码没有意义:
@Override
public Fragment getItem(int position) {
return CreateWishFormDatePaginationFragment.newInstance(position);
}
本质上,您在 position
的基础上创建了一个 Fragment
。无论删除哪个页面,position
的范围都会从 [0, iPageCount
) 变为 [0, iPageCount-1
),意思就是永远去掉最后的Fragment
。
你需要的大致如下:
public class DatePickerPagerAdapter extends FragmentStatePagerAdapter
{
private ArrayList<Integer> pageIndexes;
public DatePickerPagerAdapter(FragmentManager fm) {
super(fm);
pageIndexes = new ArrayList<>();
for (int i = 0; i < 10; i++) {
pageIndexes.add(new Integer(i));
}
}
@Override
public int getCount() {
return pageIndexes.size();
}
@Override
public Fragment getItem(int position) {
Integer index = pageIndexes.get(position);
return CreateWishFormDatePaginationFragment.newInstance(index.intValue());
}
// This is called when notifyDataSetChanged() is called
@Override
public int getItemPosition(Object object) {
// refresh all fragments when data set changed
return PagerAdapter.POSITION_NONE;
}
// Delete a page at a `position`
public void deletePage(int position)
{
// Remove the corresponding item in the data set
pageIndexes.remove(position);
// Notify the adapter that the data set is changed
notifyDataSetChanged();
}
}
有关从 FragmentStatePagerAdapter 中删除项目的更多详细信息,请参阅完整的 example。
ViewPager 不会使用上面的代码删除您的片段,因为它会将多个视图(或片段)加载到内存中。除了可见视图之外,它还将视图加载到可见视图的任一侧。这提供了从一个视图到另一个视图的平滑滚动,这使得 ViewPager 非常酷。
要达到您想要的效果,您需要做几件事。
- 将 FragmentPagerAdapter 更改为 FragmentStatePagerAdapter。这样做的原因是 FragmentPagerAdapter 将永远保留它加载到内存中的所有视图。 FragmentStatePagerAdapter 处理当前视图和可遍历视图之外的视图的位置。
覆盖适配器方法 getItemPosition(如下所示)。当我们调用 mAdapter.notifyDataSetChanged(); ViewPager 询问适配器以确定在定位方面发生了什么变化。我们使用此方法表示一切都已更改,因此重新处理所有视图定位。 这是代码...
private class MyPagerAdapter extends FragmentStatePagerAdapter { //... your existing code @Override public int getItemPosition(Object object){ return PagerAdapter.POSITION_NONE; } }