【问题标题】:Dynamically remove an item from a ViewPager with FragmentStatePagerAdapter使用 FragmentStatePagerAdapter 从 ViewPager 中动态删除项目
【发布时间】:2015-01-23 11:29:42
【问题描述】:

围绕这个话题有不少讨论

我尝试了各种解决方案(包括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 中处理添加和删除片段的正确方法是什么?

谢谢!

【问题讨论】:

    标签: android android-fragments android-viewpager android-adapter


    【解决方案1】:

    如果您想从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();
        }
    }
    

    请参阅完整的example,了解有关从 FragmentStatePagerAdapter 中删除项目 的更多详细信息。

    【讨论】:

    • 这仅在您尝试删除片段时才有效。如果您再次尝试删除另一个项目,似乎删除不起作用。
    • 在针对我的确切用例进行了一些修改之后,对我来说就像一个魅力。我特别喜欢的是让FragmentStatePagerAdapterFragmentManager 关心每个Fragment 的状态。
    • 但是这段代码 @Override public int getItemPosition(Object object) { // 当数据集改变时刷新所有片段 return PagerAdapter.POSITION_NONE; } 移除片段需要花费太多时间。你能帮忙吗
    【解决方案2】:

    ViewPager 不会使用上面的代码删除您的片段,因为它会将多个视图(或您的情况下的片段)加载到内存中。除了可见视图之外,它还将视图加载到可见视图的任一侧。这提供了从一个视图到另一个视图的平滑滚动,这使得 ViewPager 非常酷。

    要达到你想要的效果,你需要做几件事。

    1. 将 FragmentPagerAdapter 更改为 FragmentStatePagerAdapter。这样做的原因是 FragmentPagerAdapter 将永远保留它加载到内存中的所有视图。 FragmentStatePagerAdapter 处理当前视图和可遍历视图之外的视图。
    2. 重写适配器方法getItemPosition(如下所示)。当我们调用 mAdapter.notifyDataSetChanged(); ViewPager 询问适配器以确定在定位方面发生了什么变化。我们使用这种方法表示一切都发生了变化,因此重新处理所有视图定位。 这是代码...

      private class MyPagerAdapter extends FragmentStatePagerAdapter {
          //... your existing code
          @Override
          public int getItemPosition(Object object){
              return PagerAdapter.POSITION_NONE;
          }
      }
      

    【讨论】:

    • yaaaaa @PaulBurke
    猜你喜欢
    • 1970-01-01
    • 2014-09-15
    • 2013-05-09
    • 2011-04-18
    • 1970-01-01
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    相关资源
    最近更新 更多