10

我正在使用 aViewpagerFragmentPagerAdapter允许添加和删除页面。每个页面显示从互联网获得的数据。

随着新页面的添加,新的 Fragment 与该页面相关联。数据通过 AsyncTask 获取并显示在 Fragment 中。当用户选择删除页面时,想法是销毁页面和相关的 Fragment。

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

  1. 您有三个包含数据的页面:

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

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

    [第1页] [第3页]

  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();

使用调试器,它显示片段已从调用FragmentManager后删除。executePendingTransactions()但是在FrampePagerAdapters调用中mAdapter.notifyDataSetChanged(),片段被重新添加进来,然后在创建新页面时显示。

我尝试使用 FrameStatePagerAdapter,因为它应该允许破坏片段,但它不起作用。在我的 FragmentPagerAdaptergetItemPosition()方法中,我使用return FragmentAdapter.POSITION_NONE;了我遇到的另一篇 SO 文章中指出的方法。

似乎该页面的视图没有被破坏,而是被添加回新页面。我尝试removeViewAt()在新页面的视图上使用该方法,但没有奏效。


作为新手,我敢肯定我错过了一些明显的东西......

4

3 回答 3

1

您应该FragmentStatePagerAdapter从该适配器的项目列表中扩展和删除相应的项目,而不是尝试从活动中删除片段。adapter.notifyDataSetChanged()删除适配器中的项目后不要忘记调用。一旦完成,ViewPagerFragmentStatePagerAdapter照顾其余的。

于 2013-08-17T12:53:07.543 回答
0

查看您的 getCount() 方法正在返回 viewPager 中的确切项目数。是的,FragmentStatePagerAdapter 也很重要。

于 2013-10-28T05:55:56.120 回答
0

我最终得到了一个解决方案,它根据经验混合了以下知识:

  • Fragment您可以毫无问题地在尾部添加新的。
  • 您无法读取Fragment以前删除的内容,因为它java.lang.IllegalStateException: Can't change tag of fragment有时会导致,因此您必须克隆它。
  • 要删除 a你必须在方法Fragment中返回,并从.PagerAdapter.POSITION_NONEgetItemPosition(Object object)FragmentFragmentManager
  • 如果您要在不同于尾部的其他位置添加/删除/替换,则必须从要更改的位置删除所有内容,直到结束,执行这些操作,然后读取Fragment您删除的 (克隆) s。

这是一个完整的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);
        }
    }

}
于 2013-11-11T03:29:22.010 回答