在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