Android Viewpager和FragmentPagerAdapter:页面视图删除

Android Viewpager和FragmentPagerAdapter:页面视图删除,android,android-fragments,android-viewpager,Android,Android Fragments,Android Viewpager,我正在使用Viewpager和FragmentPagerAdapter来允许添加和删除页面。每个页面显示从internet获得的数据 当添加一个新页面时,一个新片段与该页面相关联。数据通过AsyncTask获得并显示在片段中。当用户选择删除页面时,其想法是销毁页面和相关片段 总的来说,这一切都很好。我看到的问题如下: // Destroy fragment for this page DataListFragment curFrag = getFragmentByName(curre

我正在使用
Viewpager
FragmentPagerAdapter
来允许添加和删除页面。每个页面显示从internet获得的数据

当添加一个新页面时,一个新片段与该页面相关联。数据通过AsyncTask获得并显示在片段中。当用户选择删除页面时,其想法是销毁页面和相关片段

总的来说,这一切都很好。我看到的问题如下:

   // Destroy fragment for this page
   DataListFragment curFrag = getFragmentByName(currentPage);
   FragmentManager fm = getSupportFragmentManager();
   fm.beginTransaction().remove(curFrag).commit();
   fm.executePendingTransactions();
   curFrag = null;

   // Remove page and update adapter
   mPageTitles.remove(position);        
   mAdapter.notifyDataSetChanged();
  • 您有三个包含数据的页面:

    [第1页][第2页][第3页]

  • 删除除最后一页以外的任何页面,如第2页;第2页根据需要消失:

    [第1页][第3页]

  • 添加新页面;但新页面显示的不是空白的新页面,而是第3页的数据(视图)

    [第1页][第3页][第4页,但显示第3页的视图/数据,应为空白]


  • “我的活动”中的页面删除代码如下:

       // Destroy fragment for this page
       DataListFragment curFrag = getFragmentByName(currentPage);
       FragmentManager fm = getSupportFragmentManager();
       fm.beginTransaction().remove(curFrag).commit();
       fm.executePendingTransactions();
       curFrag = null;
    
       // Remove page and update adapter
       mPageTitles.remove(position);        
       mAdapter.notifyDataSetChanged();
    
    使用调试器,它显示在调用
    executePendingTransactions()
    之后从
    FragmentManager
    中删除片段。但是在
    FrampePagerAdapters
    调用中,
    mAdapter.notifyDataSetChanged()
    ,片段被重新添加,然后在创建新页面时显示

    我尝试使用FrameStatePagerAdapter,因为这应该允许销毁片段,但它不起作用。在FragmentPagerAdapter的
    getItemPosition()
    方法中,我使用
    返回FragmentAdapter.POSITION\u NONE
    似乎该页面的视图没有被破坏,而是被添加回新页面。我尝试在新页面的视图上使用
    removeViewAt()
    方法,但没有成功



    作为新手,我确信我缺少了一些明显的东西…

    您应该扩展
    FragmentStatePagerAdapter
    并从适配器中的项目列表中删除相应的项目,而不是尝试从活动中删除片段。删除适配器中的项目后,不要忘记调用适配器。notifyDataSetChanged()
    。完成后,
    ViewPager
    FragmentStatePagerAdapter
    将处理其余部分。

    请参见getCount()方法返回ViewPager中的确切项数。是的,碎纸机也很重要

    我最终找到了一个解决方案,它结合了以下基于经验的知识:

    • 您可以在尾部添加一个新的
      片段
    • 您无法读取以前删除的
      片段
      ,因为它会导致
      java.lang.IllegalStateException:有时无法更改片段的标记
      ,因此您必须克隆它
    • 要删除
      片段
      ,必须在方法
      getItemPosition(Object Object)
      中返回
      PagerAdapter.POSITION\u NONE
      ,然后从
      片段管理器
      中删除
      片段
    • 如果您在不同于尾部的其他位置添加/删除/替换,则必须从要更改的位置删除所有内容,直到结束,然后读取您删除的(克隆的)
      片段
    这里是一个完整的
    FragmentActivity
    代码,带有
    FragmentPagerAdapter
    ,它有3种添加、删除和替换选项卡的方法:

    public class TabTestActivity extends FragmentActivity implements
            ActionBar.TabListener {
        private SectionsPagerAdapter mSectionsPagerAdapter;
        private ViewPager mViewPager;
        private static int tabCount = 0;
        private static String labelString = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            labelString = getString(R.string.title_section);
            setContentView(R.layout.activity_tab_test);
            final ActionBar actionBar = getActionBar();
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
            mSectionsPagerAdapter = new SectionsPagerAdapter(
                    getSupportFragmentManager());
            mViewPager = (ViewPager) findViewById(R.id.pager);
            mViewPager.setAdapter(mSectionsPagerAdapter);
            mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                        @Override
                        public void onPageSelected(final int position) {
                            (new Handler()).postDelayed(new Runnable() {
    
                                @Override
                                public void run() {
                                    actionBar.setSelectedNavigationItem(position);
                                }
    
                            }, 1);
                        }
                    });
    
            for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
                actionBar.addTab(actionBar.newTab()
                        .setText(mSectionsPagerAdapter.getPageTitle(i))
                        .setTabListener(this));
            }
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.tab_test, menu);
            return true;
        }
    
        public void addNewTab() {
            int position = (mSectionsPagerAdapter.getCount() > 0 ? mViewPager.getCurrentItem() : 0);
            mSectionsPagerAdapter.insertFragment(position);
            mViewPager.setCurrentItem(position, true);
        }
    
        public void removeTab() {
            if (mSectionsPagerAdapter.getCount() > 0) {
                int position = mViewPager.getCurrentItem();
                mSectionsPagerAdapter.removeFragment(position);
            }
        }
    
        public void replaceTab() {
            if (mSectionsPagerAdapter.getCount() > 0) {
                int position = mViewPager.getCurrentItem();
                mSectionsPagerAdapter.replaceFragment(position);            
                mViewPager.setCurrentItem(position, false);
            }
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
            case R.id.action_add_tab:
                addNewTab();
                return true;
            case R.id.action_remove_tab:
                removeTab();
                return true;
            case R.id.action_replace_tab:
                replaceTab();
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    
        @Override
        public void onTabSelected(ActionBar.Tab tab,
                FragmentTransaction fragmentTransaction) {
            mViewPager.setCurrentItem(tab.getPosition());
        }
    
        @Override
        public void onTabUnselected(ActionBar.Tab tab,
                FragmentTransaction fragmentTransaction) {
        }
    
        @Override
        public void onTabReselected(ActionBar.Tab tab,
                FragmentTransaction fragmentTransaction) {
        }
    
        public class SectionsPagerAdapter extends FragmentPagerAdapter {
    
            private List<Fragment> currentFragments;
            private FragmentManager fragmentManager;
    
            public SectionsPagerAdapter(FragmentManager fm) {
                super(fm);
                fragmentManager = fm;
                currentFragments = new ArrayList<Fragment>();
            }
    
            public void insertFragment(int position) {
                // Remove fragments from position
                List<Fragment> fragmentsToRemove = new ArrayList<Fragment>(currentFragments.subList(position, currentFragments.size()));
                int i = currentFragments.size() - 1;
                int j = -1;
                int k = i;
                while (i >= position) {
                    currentFragments.remove(i);
                    i--;
                    j++;
                }
                notifyDataSetChanged();
                final ActionBar actionBar = getActionBar();
                while (k >= position) {
                    actionBar.removeTabAt(k);
                    k--;
                }
                android.support.v4.app.FragmentTransaction transaction = fragmentManager.beginTransaction();
                while (j >= 0) {
                    Fragment fragmentToRemove = fragmentsToRemove.get(j);
                    transaction.detach(fragmentToRemove);
                    transaction.remove(fragmentToRemove);
                    j--;
                }
                transaction.commit();
                fragmentManager.executePendingTransactions();
                notifyDataSetChanged();
                // Add new fragment
                Fragment fragment = new DummySectionFragment();
                currentFragments.add(position, fragment);
                notifyDataSetChanged();
                actionBar.addTab(actionBar.newTab()
                        .setText(mSectionsPagerAdapter.getPageTitle(position))
                        .setTabListener(TabTestActivity.this), position);
                // Readd fragments
                if (fragmentsToRemove.size() > 0) {
                    i = 1;
                    for (Fragment fragmentToRemove : fragmentsToRemove) {
                        currentFragments.add(DummySectionFragment.cloneExistingFragment((DummySectionFragment)fragmentToRemove));
                        notifyDataSetChanged();
                        actionBar.addTab(actionBar.newTab()
                                .setText(mSectionsPagerAdapter.getPageTitle(position + i))
                                .setTabListener(TabTestActivity.this), position + i);
                        i++;
                    }
                }
            }
    
            public void removeFragment(int position) {
                // Remove fragments from position
                List<Fragment> fragmentsToRemove = new ArrayList<Fragment>(currentFragments.subList(position, currentFragments.size()));
                int i = currentFragments.size() - 1;
                int j = -1;
                int k = i;
                while (i >= position) {
                    currentFragments.remove(i);
                    i--;
                    j++;
                }
                notifyDataSetChanged();
                final ActionBar actionBar = getActionBar();
                while (k >= position) {
                    actionBar.removeTabAt(k);
                    k--;
                }
                android.support.v4.app.FragmentTransaction transaction = fragmentManager.beginTransaction();
                while (j >= 0) {
                    Fragment fragmentToRemove = fragmentsToRemove.get(j);
                    transaction.detach(fragmentToRemove);
                    transaction.remove(fragmentToRemove);
                    j--;
                }
                transaction.commitAllowingStateLoss();
                fragmentManager.executePendingTransactions();
                notifyDataSetChanged();
                // Readd fragments (except one)
                if (fragmentsToRemove.size() > 1) {
                    i = 0;
                    for (Fragment fragment : fragmentsToRemove.subList(1, fragmentsToRemove.size())) {
                        currentFragments.add(DummySectionFragment.cloneExistingFragment((DummySectionFragment)fragment));
                        notifyDataSetChanged();
                        actionBar.addTab(actionBar.newTab()
                                .setText(mSectionsPagerAdapter.getPageTitle(position + i))
                                .setTabListener(TabTestActivity.this), position + i);
                        i++;
                    }
                }
            }
    
            public void replaceFragment(int position) {
                // Remove fragments from position
                List<Fragment> fragmentsToRemove = new ArrayList<Fragment>(currentFragments.subList(position, currentFragments.size()));
                int i = currentFragments.size() - 1;
                int j = -1;
                int k = i;
                while (i >= position) {
                    currentFragments.remove(i);
                    i--;
                    j++;
                }
                notifyDataSetChanged();
                final ActionBar actionBar = getActionBar();
                while (k >= position) {
                    actionBar.removeTabAt(k);
                    k--;
                }
                android.support.v4.app.FragmentTransaction transaction = fragmentManager.beginTransaction();
                while (j >= 0) {
                    Fragment fragmentToRemove = fragmentsToRemove.get(j);
                    transaction.detach(fragmentToRemove);
                    transaction.remove(fragmentToRemove);
                    j--;
                }
                transaction.commit();
                fragmentManager.executePendingTransactions();
                notifyDataSetChanged();
                // Add new fragment
                Fragment fragment = new DummySectionFragment();
                currentFragments.add(position, fragment);
                notifyDataSetChanged();
                actionBar.addTab(actionBar.newTab()
                        .setText(mSectionsPagerAdapter.getPageTitle(position))
                        .setTabListener(TabTestActivity.this), position);
                // Readd fragments (except one)
                if (fragmentsToRemove.size() > 0) {
                    i = 1;
                    for (Fragment fragmentToRemove : fragmentsToRemove.subList(1, fragmentsToRemove.size())) {
                        currentFragments.add(DummySectionFragment.cloneExistingFragment((DummySectionFragment)fragmentToRemove));
                        notifyDataSetChanged();
                        actionBar.addTab(actionBar.newTab()
                                .setText(mSectionsPagerAdapter.getPageTitle(position + i))
                                .setTabListener(TabTestActivity.this), position + i);
                        i++;
                    }
                }
            }
    
            @Override
            public Fragment getItem(int position) {
                if (currentFragments == null) {
                    currentFragments = new ArrayList<Fragment>();
                }
                while (currentFragments.size() <= position) {
                    currentFragments.add(null);
                }
                if (currentFragments.get(position) != null) {
                    return currentFragments.get(position);
                }
                Fragment fragment = new DummySectionFragment();
                currentFragments.set(position, fragment);
                return fragment;
            }
    
            @Override
            public int getCount() {
                return currentFragments.size();
            }
    
            @Override
            public int getItemPosition(Object object) {
                int position = currentFragments.indexOf(object);
                if (position == -1) {
                    return PagerAdapter.POSITION_NONE;
                }
                return position;
            }
    
            @Override
            public CharSequence getPageTitle(int position) {
                return ((DummySectionFragment)getItem(position)).getTitle();
            }
        }
    
        public static class DummySectionFragment extends Fragment {
            private int sectionNumber;
    
            public DummySectionFragment() {
                super();
                sectionNumber = ++tabCount;
            }
    
            public static DummySectionFragment cloneExistingFragment(DummySectionFragment fragment) {
                DummySectionFragment cloned = new DummySectionFragment();
                // Hack for avoiding autoincrement
                --tabCount;
                cloned.sectionNumber = fragment.getSectionNumber();
                return cloned;
            }
    
            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container,
                    Bundle savedInstanceState) {
                View rootView = inflater.inflate(R.layout.fragment_tab_test_dummy,
                        container, false);
                TextView dummyTextView = (TextView) rootView
                        .findViewById(R.id.section_label);
                dummyTextView.setText(String.format(labelString, sectionNumber));
                return rootView;
            }
    
            public int getSectionNumber() {
                return sectionNumber;
            }
    
            public String getTitle() {
                return String.format(labelString, sectionNumber);
            }
        }
    
    }
    
    公共类TabTestActivity扩展了FragmentActivity实现
    ActionBar.TabListener{
    私人部门SPAGERAAdapter MSECTIONSPAGERAAdapter;
    私有视图寻呼机mViewPager;
    私有静态int tabCount=0;
    私有静态字符串labelString=null;
    @凌驾
    创建时受保护的void(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    labelString=getString(R.string.title_部分);
    setContentView(R.layout.activity\u tab\u test);
    最终ActionBar ActionBar=getActionBar();
    actionBar.setNavigationMode(actionBar.NAVIGATION\u MODE\u选项卡);
    mSectionsPagerAdapter=新节spageradapter(
    getSupportFragmentManager());
    mViewPager=(ViewPager)findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);
    mViewPager.setOnPageChangeListener(新的ViewPager.SimpleOnPageChangeListener(){
    @凌驾
    已选择页面上的公共无效(最终整型位置){
    (新的处理程序()).postDelayed(新的可运行(){
    @凌驾
    公开募捐{
    actionBar.setSelectedNavigationItem(位置);
    }
    }, 1);
    }
    });
    对于(int i=0;i0?mviewpage.getCurrentItem():0);
    mSectionsPagerAdapter.insertFragment(位置);
    mViewPager.setCurrentItem(位置,true);
    }
    公共无效删除选项卡(){
    如果(msActionSpagerAdapter.getCount()>0){
    int position=mViewPager.getCurrentItem();
    mSectionsPagerAdapter.removeFragment(位置);
    }
    }
    公共void replaceTab(){
    如果(msActionSpagerAdapter.getCount()>0){
    int position=mViewPager.getCurrentItem();
    mSectionsPagerAdapter.replaceFragment(位置);
    mViewPager.setCurrentItem(位置,false);