2012-09-07 21 views

Trả lời

31

Có. Tôi sẽ thử và trả lời trường hợp của bạn bằng cách chỉ ra cách tôi đã làm nó, và tôi sẽ trình bày một ví dụ cho trường hợp của bạn bên dưới mẫu mã của tôi.

Về cơ bản, để thực hiện việc này, bạn phải theo dõi vị trí mà Phân đoạn của bạn có. Dưới đây là triển khai tôi đã sử dụng cho FragmentPagerAdapter, sử dụng ArrayList làm nguồn dữ liệu của nó.

public class MyFragmentPagerAdapter extends FragmentPagerAdapter { 

    private HashMap<Long, Fragment> mItems 
        = new HashMap<Long, Fragment>(); 

    private ArrayList<MyObject> dataset; 

    public MyFragmentPagerAdapter(ArrayList<MyObject> objects) { 
     this.dataset = objects; 
    } 

    @Override 
    public int getCount() { 
     return dataset.size(); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     long id = getItemId(position); 

     if(mItems.get(id) != null) { 
      // caching to prevent multiple instances of the same fragment 
      // for the same position/id 
      return mItems.get(id); 
     } 

     Fragment f = Fragment.newInstance(); 

     mItems.put(id, f); 

     return f; 
    } 

    @Override 
    public long getItemId(int position) { 
     // return a unique id 
     return dataset.get(position).getUniqueId(); 
    } 

    @Override 
    public int getItemPosition(Object object) { 
     /* 
     * Purpose of this method is to check whether an item in the adapter 
     * still exists in the dataset and where it should show. 
     * For each entry in dataset, request its Fragment. 
     * 
     * If the Fragment is found, return its (new) position. There's 
     * no need to return POSITION_UNCHANGED; ViewPager handles it. 
     * 
     * If the Fragment passed to this method is not found, remove all 
     * references and let the ViewPager remove it from display by 
     * by returning POSITION_NONE; 
     */ 
     Fragment f = (Fragment) object; 

     for(int i = 0; i < getCount(); i++) { 

      Fragment item = (Fragment) getItem(i); 
      if(item.equals(f)) { 
       // item still exists in dataset; return position 
       return i; 
      } 
     } 

     // if we arrive here, the data-item for which the Fragment was created 
     // does not exist anymore. 

     // Also, cleanup: remove reference to Fragment from mItems 
     for(Map.Entry<Long, MainListFragment> entry : mItems.entrySet()) { 
      if(entry.getValue().equals(f)) { 
       mItems.remove(entry.getKey()); 
       break; 
      } 
     } 

     // Let ViewPager remove the Fragment by returning POSITION_NONE. 
     return POSITION_NONE; 
    } 
} 

Bây giờ nếu bạn xóa một mục từ tập dữ liệu (this.dataset) và gọi notifyDataSetChanged() trên bạn thể hiện của MyFragmentPagerAdapter, nó sẽ loại bỏ các mục từ ViewPager (ngay cả khi nó đang được xem).

Giả sử this.dataset chứa 5 mục và bạn muốn di chuyển # 2 vào cuối ViewPager. Để thực hiện việc này, bạn sẽ phải định vị mục số 2 vào cuối nguồn dữ liệu của mình (hoặc qua Collection.Sort hoặc một số cách khác). Tôi sẽ chỉ cho bạn một cách dễ dàng.

ArrayList<MyObject> list = new ArrayList<>(); 
MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(list); 
viewpager.setAdapter(adapter); 

... 

MyObject item = list.get(2); 
list.remove(item); 
list.add(item); // now it's positioned at the end of the list 
adapter.notifyDataSetChanged(); // voilá, that should do the trick! 

adapter.notifyDataSetChanged() cuối cùng gọi viewpager.dataSetChanged(), nó sẽ gọi adapter.getItemPosition(..) trên mỗi trang của nó. Kết quả của cuộc gọi phương thức đó xác định nếu và nơi trang (Fragment trong trường hợp này) sẽ hiển thị.

+1

Rất dễ hiểu. Bất kỳ lý do nào khiến bạn không sử dụng FragmentStatePagerAdapter với việc triển khai này? Danh sách mItems của bạn có làm cho lớp học quy mô lớn mất tất cả các lý do cho khả năng sử dụng của nó không? – jbenowitz

+0

Điều này cũng không giúp tôi. Tôi đang loại bỏ các mục, hoàn toàn. Bất cứ khi nào tôi chuyển sang mục tiếp theo, hãy xóa mục trước đó, mục đó sẽ vuốt nhưng giữa vuốt sẽ thay đổi mục tiếp theo thành mục sau đó. Trực quan: mục A, B, C trong bộ chuyển đổi Xem A, Vuốt sang B. Bắt đầu xóa A, giữa swipe sang B, Flash tới C. – jbenowitz

+0

Có, điều này được mong đợi. Nếu bạn loại bỏ A, B sẽ là pos == 0, và C pos == 1. Mục hiện tại của bạn ('viewPager.setCurrentItem (int)') được đặt thành 1 khi vuốt từ A sang B. Khi bạn xóa A, vị trí hiện tại sẽ vẫn là 1, có nghĩa là 'ViewPager' sẽ nhảy tới C.Bạn có thể sửa lỗi này bằng cách đặt 'viewPager.setCurrentItem (adapter.getItemPosition (fragment-B))' khi bạn xóa A. – Reinier

1

Tôi vừa đọc hết tất cả những điều này.

Cách thông thường của việc sử dụng một ViewPager là bằng cách có một lớp PagerAdapter cung cấp cho nó đúng trang vào đúng thời điểm. Có các lớp con của PagerAdapter, FragmentPagerAdapter và FragmentStatePagerAdapter dễ sử dụng hơn.

Tuy nhiên, để có thể thay đổi thứ tự trang, bạn sẽ phải viết lớp con của riêng bạn của PagerAdapter. Về cơ bản có hai cách mà ViewPager biết bạn đang ở trang nào: số trang và một đối tượng khóa mà bộ điều hợp đã cho nó. Do đó bạn nên có thể thay đổi thứ tự mà không ViewPager bị mất quá nhiều.

Chi tiết gory về cách thực hiện được thực hiện trên this page. Tôi chưa cố gắng nhưng tôi sẽ trong những tuần tới. Tôi nghĩ rằng trang đó không nói mọi thứ. Nó không đề cập đến phương thức getItem() mà hầu hết các lớp Adapter phải có. Vì vậy, tôi thực sự chưa thấy các trang được thêm vào ViewPager như thế nào.

Thời gian tìm và đọc một số mã mẫu.

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