【问题标题】:Viewpager and FragmentPagerAdapter: Page view removalViewpager 和 FragmentPagerAdapter:页面视图移除
【发布时间】:2012-09-07 09:53:58
【问题描述】:

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

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

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

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

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

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

    [第 1 页] [第 3 页]

  3. 您添加了一个新页面;但新页面不是空白的新页面,而是显示第 3 页的数据(视图)。

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


我的activity中的页面移除代码如下:

   // 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() 方法中,我使用了 return FragmentAdapter.POSITION_NONE;,正如我遇到的另一篇 SO 文章中所指出的那样。

似乎该页面的视图没有被破坏,而是重新添加到新页面中。我尝试在新页面的视图上使用removeViewAt() 方法,但这不起作用。


作为新手,我确定我遗漏了一些明显的东西......

【问题讨论】:

  • 我不确定这是否显而易见。我也遇到了这个问题。你解决了吗?这里可能有答案:stackoverflow.com/questions/12510404/…
  • 你能告诉我们你的覆盖方法吗:public Fragment getItem(int position)
  • 删除片段时,不会将其从适配器中删除。这就是它再次出现的原因。您需要从您的适配器中删除它(不是视图,而是您在 getItem() 方法中使用的项目)。第 4 个片段看起来像第三个,因为它重用了片段,就像 ListView 的适配器一样。您在适配器逻辑中有错误。显示您的适配器类

标签: android android-fragments android-viewpager


【解决方案1】:

您应该扩展FragmentStatePagerAdapter 并从该适配器的项目列表中删除相应的项目,而不是尝试从活动中删除片段。删除适配器中的项目后,不要忘记致电adapter.notifyDataSetChanged()。完成后,ViewPager 和 FragmentStatePagerAdapter 将负责其余的工作。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      我最终得到了一个基于经验混合以下知识的解决方案:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-04-02
        • 2012-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多