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ị.
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
Đ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
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