2012-09-07 42 views
10

Tôi đang sử dụng Viewpager với số FragmentPagerAdapter để cho phép thêm và xóa trang. Mỗi trang hiển thị dữ liệu thu được từ internet.Viewpager và FragmentPagerAdapter: Xóa trang xem

Khi một trang mới được thêm vào, một Phân đoạn mới được liên kết với trang đó. Dữ liệu thu được thông qua AsyncTask và được hiển thị trong Fragment. Khi người dùng chọn xóa một trang, ý tưởng là phá hủy trang và Phân đoạn liên quan.

Nói chung, tất cả đều hoạt động tốt. Vấn đề tôi đang nhìn thấy là như sau:

  1. Bạn có ba trang với các dữ liệu:

    [Trang 1] [Trang 2] [Trang 3]

  2. Bạn xóa bất kỳ trang khác trang cuối cùng, nói trang 2; Trang 2 biến mất như mong muốn:

    [Trang 1] [Trang 3]

  3. Bạn thêm một trang mới; nhưng thay vì trang trống, mới, trang mới hiển thị dữ liệu (xem) từ trang 3.

    [Trang 1] [Trang 3] [Trang 4, nên là blank]


việc loại bỏ mã trang trong hoạt động của tôi là như sau:

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

Sử dụng trình gỡ lỗi, nó cho thấy rằng các mảnh vỡ được lấy ra từ các FragmentManager sau cuộc gọi executePendingTransactions(). Nhưng trong cuộc gọi FrampePagerAdapters, mAdapter.notifyDataSetChanged(), đoạn được thêm lại vào và sau đó được hiển thị khi trang mới được tạo.

Tôi đã thử sử dụng FrameStatePagerAdapter, vì điều đó sẽ cho phép phá hủy các đoạn, nhưng nó không hoạt động. Trong phương thức getItemPosition() của FragmentPagerAdapter, tôi sử dụng return FragmentAdapter.POSITION_NONE; như được chỉ ra trong một bài viết SO khác mà tôi đã xem xét.

Dường như Chế độ xem cho trang đó không bị hủy, nhưng sau đó được thêm lại vào trang mới. Tôi đã thử sử dụng phương thức removeViewAt() trên giao diện của trang mới, nhưng điều đó không hiệu quả.


Là mới đến này, tôi chắc chắn rằng tôi đang thiếu một cái gì đó rõ ràng ...

+0

Tôi không chắc chắn rằng đó là một cái gì đó rõ ràng. Tôi cũng đang gặp vấn đề này. Bạn đã giải quyết nó? Có thể có câu trả lời ở đây: http://stackoverflow.com/questions/12510404/reorder-pages-in-fragmentstatepageradapter-using-getitempositionobject-object –

+1

Bạn có thể chỉ cho chúng tôi phương pháp ghi đè của bạn: public fragment getItem (int position) – Gomino

+0

Khi nào bạn đang xóa một đoạn, bạn không xóa nó khỏi bộ điều hợp. Đó là lý do tại sao nó lại xuất hiện. Bạn cần phải loại bỏ nó khỏi adapter của bạn (không phải xem, nhưng Item, mà bạn sử dụng trong phương thức getItem()). đoạn thứ 4 trông giống như phần thứ ba vì nó sử dụng lại đoạn, giống như adapter của ListView. Bạn có sai lầm trong logic bộ điều hợp. Hiển thị lớp bộ điều hợp của bạn –

Trả lời

1

Bạn nên thay vì mở rộng FragmentStatePagerAdapter và loại bỏ mục tương ứng từ danh sách các mục trong bộ chuyển đổi đó, thay vì cố gắng để xóa Phân đoạn khỏi hoạt động. Đừng quên gọi adapter.notifyDataSetChanged() sau khi bạn đã xóa một mục trong bộ điều hợp. Sau khi hoàn tất, ViewPagerFragmentStatePagerAdapter sẽ xử lý phần còn lại.

0

Xem phương thức getCount() của bạn trả về số lượng chính xác các mục trong viewPager. Và có, FragmentStatePagerAdapter cũng tính.

0

Tôi đã kết thúc với một giải pháp mà hỗn hợp các kiến ​​thức sau đây dựa trên kinh nghiệm:

  • Bạn có thể thêm mới Fragment ở đuôi không có vấn đề.
  • Bạn không thể thêm lại Fragment đã bị xóa trước đó, vì nó dẫn đến java.lang.IllegalStateException: Can't change tag of fragment đôi khi, vì vậy bạn phải sao chép nó.
  • Để xóa Fragment bạn phải trả lại PagerAdapter.POSITION_NONE theo phương pháp getItemPosition(Object object) và xóa Fragment từ FragmentManager.
  • Nếu bạn thêm/xóa/thay thế ở vị trí khác với đuôi, bạn phải xóa mọi thứ khỏi vị trí bạn đang thay đổi cho đến khi kết thúc, thực hiện công cụ và sau đó readd (cloned) Fragment s mà bạn đã xóa .

Dưới đây là những quy tắc FragmentActivity hoàn chỉnh với một FragmentPagerAdapter có 3 phương pháp để thêm, loại bỏ và thay thế tab:

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

} 
Các vấn đề liên quan