在Android中使用Viewpager
,是否有可能以編程方式將任何頁面移動到最後?例如,我有五頁,並且希望將第2頁移動到最後一個位置(第5個位置),因此第3頁變成了第2個,第4個變成了第3個,而第5個變成了第4個?Android ViewPager:移動任何頁面以編程方式結束?
謝謝
在Android中使用Viewpager
,是否有可能以編程方式將任何頁面移動到最後?例如,我有五頁,並且希望將第2頁移動到最後一個位置(第5個位置),因此第3頁變成了第2個,第4個變成了第3個,而第5個變成了第4個?Android ViewPager:移動任何頁面以編程方式結束?
謝謝
是的。我會試着回答你的情況,通過展示我是如何做到的,我將在我的代碼示例下面爲您的案例展示一個示例。
基本上,要做到這一點,你必須跟蹤碎片的位置。下面是我用於我的FragmentPagerAdapter
的實現,它使用ArrayList作爲其數據源。現在
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;
}
}
如果從數據集(this.dataset
)刪除一個項目並在您的MyFragmentPagerAdapter
實例調用notifyDataSetChanged()
,它將從ViewPager(即使真實當前正在查看它)刪除該項目。
假設this.dataset
包含5個項目,並且您想將#2移動到ViewPager的末尾。要做到這一點,您必須將項目#2定位到數據源的末尾(通過Collection.Sort
或其他方式)。我會告訴你簡單的方法。
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()
最後調用viewpager.dataSetChanged()
,進而調用它的每個頁面的adapter.getItemPosition(..)
。該方法調用的結果決定頁面(本例中爲片段)是否以及在哪裏顯示。
我剛讀到這一切。
使用ViewPager的常用方法是讓PagerAdapter類在適當的時候爲其提供正確的頁面。 PagerAdapter,FragmentPagerAdapter和FragmentStatePagerAdapter有很好的子類,它們更易於使用。
但是,爲了能夠更改頁面順序,您將不得不編寫自己的PagerAdapter的子類。基本上,ViewPager可以通過兩種方法知道您所在的頁面:頁碼,以及適配器提供的關鍵對象。因此,您應該能夠在ViewPager不會丟失的情況下更改訂單。
它是如何完成的血淋淋的細節在this page。我還沒有嘗試,但我會在幾周後。我認爲該網頁並沒有說明一切。它沒有提到大多數適配器類必須具有的getItem()方法。所以我真的還沒有看到如何將頁面添加到ViewPager。
找到並閱讀一些示例代碼的時間。
非常容易理解。任何你沒有在這個實現中使用FragmentStatePagerAdapter的原因?你的項目列表是否會讓大型班級失去所有可用性的理由? – jbenowitz
這也似乎沒有幫助我。我正在刪除項目,完全。每當我去到下一個項目,刪除了前一個項目,它會刷卡,但中間刷卡後,將下一個項目更改爲項目。目視: 適配器中的A,B,C項 查看A,滑動到B.開始刪除A,中間滑動到B,閃爍到C. – jbenowitz
是的,這是預期的。如果刪除A,則B將爲pos == 0,並且C pos == 1。當從A滑動到B時,您當前的項目('viewPager.setCurrentItem(int)')被設置爲1.當您移除A時,當前位置仍然是1,這意味着'ViewPager'將跳轉到C.您可以通過在刪除A時設置'viewPager.setCurrentItem(adapter.getItemPosition(fragment-B))'來糾正此問題。# – Reinier