Android ViewPager: Move any page to end programatically?

前端 未结 2 2111
星月不相逢
星月不相逢 2020-12-09 00:01

Using the Viewpager in Android, is it possible to programmatically move any page to the end? For example, I have five pages and want to move page #2 to the last

2条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-09 00:17

    Yes. I'll try and answer your case by showing how I did it, and I'll show an example for your case below my code sample.

    Basically, to accomplish this you have to keep track which position your Fragments have. Below is the implementation I used for my FragmentPagerAdapter, which uses an ArrayList as its data source.

    public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
    
        private HashMap mItems
                        = new HashMap();
    
        private ArrayList dataset;
    
        public MyFragmentPagerAdapter(ArrayList 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 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;
        }
    }
    

    Now if you remove an item from the dataset (this.dataset) and call notifyDataSetChanged() on your instance of MyFragmentPagerAdapter, it will remove the item from the ViewPager (even if it's currently being viewed).

    Let's say this.dataset contains 5 items, and you want to move #2 to the end of the ViewPager. To accomplish this, you'll have to position item#2 to the end of your datasource (either via Collection.Sort or some other way). I'll just show you the easy way.

    ArrayList 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() eventually calls viewpager.dataSetChanged(), which in turn calls adapter.getItemPosition(..) on each of its pages. The result of that method call determines if and where the page (Fragment in this case) will show up.

提交回复
热议问题