web-dev-qa-db-fra.com

Ajouter/supprimer des pages à ViewPager dynamiquement

Je voudrais ajouter ou supprimer des pages de mon pageur de vue dynamiquement. Est-ce possible?

54

Oui, puisque ViewPager obtient les vues enfant d'un PagerAdapter, vous pouvez ajouter de nouvelles pages/supprimer des pages dessus et appeler .notifyDataSetChanged () pour le recharger.

19

Oui. Vous pouvez ajouter ou supprimer des vues de manière dynamique au PagerAdapter qui les fournit au ViewPager et appeler notifyDataSetChanged() à partir du PagerAdapter pour alerter le ViewPager concerné des modifications. Toutefois, lorsque vous procédez ainsi, vous devez remplacer la getItemPosition(Object) du PagerAdapter, qui indique si les éléments qu’ils affichent actuellement ont changé de position. Par défaut, cette fonction est définie sur POSITION_UNCHANGED. Par conséquent, ViewPager ne s'actualisera pas immédiatement si vous ne substituez pas cette méthode. Par exemple,

public class mAdapter extends PagerAdapter {
    List<View> mList;

    public void addView(View view, int index) {
        mList.add(index, view);
        notifyDataSetChanged();
    }

    public void removeView(int index) {
        mList.remove(index);
        notifyDataSetChanged();
    }

    @Override
    public int getItemPosition(Object object)) {
        if (mList.contains(object) {
            return mList.indexOf(object);
        } else {
            return POSITION_NONE;
        }
    }
}

Toutefois, si vous souhaitez simplement ajouter ou supprimer temporairement la vue, mais pas du jeu de données de PagerAdapter, essayez d'utiliser setPrimaryItem(ViewGroup, int, Object) pour accéder à une vue particulière dans les données de PagerAdapter et destroyItem(ViewGroup, int, Object) pour supprimer une vue de l'affichage.

24
CodePro_NotYet

Oui, le code devrait être comme ça:

public int addPage(View view, int position) {
        if ((position >= 0) && (position < getSize())) {
            myPagerAdapter.mListViews.add(position, view);
            myPagerAdapter.notifyDataSetChanged();
            return position;
        } else {
            return -1;
        }
    }

public View removePage(int position) {
        if ((position < 0) || (position >= getSize()) || (getSize()<=1)) {
            return null;
        } else {
            if (position == mPager.getCurrentItem()) {
                if(position == (getSize()-1)) {
                    mPager.setCurrentItem(position-1);
                } else if (position == 0){
                    mPager.setCurrentItem(1);
                }
            }
            View tempView = myPagerAdapter.mListViews.remove(position);
            myPagerAdapter.notifyDataSetChanged();
            return tempView;
        }
    }

Mais il y a un bug. Si l'élément actuel est 0 et que vous souhaitez supprimer la page 0, l'écran ne sera pas actualisé instantanément. Je n'ai pas trouvé de solution à ce problème.

16
tc007733

Je suis sûr que vous avez créé un adaptateur en étendant PageAdapter. Il existe donc une méthode:

 @Override
 public void destroyItem(View collection, int position, Object view) {
           ((ViewPager) collection).removeView((View) view);
 }

Pour un exemple détaillé identique, il suffit de lire cet exemple .

3
Paresh Mayani

Voici une solution alternative à cette question. Mon adaptateur:

private class PagerAdapter extends FragmentPagerAdapter implements 
              ViewPager.OnPageChangeListener, TabListener {

    private List<Fragment> mFragments = new ArrayList<Fragment>();
    private ViewPager mPager;
    private ActionBar mActionBar;

    private Fragment mPrimaryItem;

    public PagerAdapter(FragmentManager fm, ViewPager vp, ActionBar ab) {
        super(fm);
        mPager = vp;
        mPager.setAdapter(this);
        mPager.setOnPageChangeListener(this);
        mActionBar = ab;
    }

    public void addTab(PartListFragment frag) {
        mFragments.add(frag);
        mActionBar.addTab(mActionBar.newTab().setTabListener(this).
                            setText(frag.getPartCategory()));
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

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

    /** (non-Javadoc)
     * @see Android.support.v4.app.FragmentStatePagerAdapter#setPrimaryItem(Android.view.ViewGroup, int, Java.lang.Object)
     */
    @Override
    public void setPrimaryItem(ViewGroup container, int position,
            Object object) {
        super.setPrimaryItem(container, position, object);
        mPrimaryItem = (Fragment) object;
    }

    /** (non-Javadoc)
     * @see Android.support.v4.view.PagerAdapter#getItemPosition(Java.lang.Object)
     */
    @Override
    public int getItemPosition(Object object) {
        if (object == mPrimaryItem) {
            return POSITION_UNCHANGED;
        }
        return POSITION_NONE;
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        mPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) { }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) { }

    @Override
    public void onPageScrollStateChanged(int arg0) { }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) { }

    @Override
    public void onPageSelected(int position) {
        mActionBar.setSelectedNavigationItem(position);
    }

    /**
     * This method removes the pages from ViewPager
     */
    public void removePages() {
        mActionBar.removeAllTabs();

                    //call to ViewPage to remove the pages
        vp.removeAllViews();
        mFragments.clear();

        //make this to update the pager
        vp.setAdapter(null);
        vp.setAdapter(pagerAdapter);
    }
}

Code à supprimer et à ajouter dynamiquement

//remove the pages. basically call to method removeAllViews from ViewPager
pagerAdapter.removePages();

pagerAdapter.addPage(pass your fragment);

Après l’avis de Peri Hartman , cela a commencé à fonctionner après que j’ai défini null sur l’adaptateur ViewPager et que je le remette à nouveau après la suppression des vues. Avant cela, la page 0 ne montrait pas le contenu de sa liste.

3
thalespf

Tout d'abord: remplacer la méthode pagerAdapter "getItemPosition" 

@Override
public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
}

Deuxièmement: supprimez la liaison de données avec adapter.et appelez adapter.notifydatachanged

2
howerknea
@Bind(R.id.pager)
ViewPager pager;
int pos = pager.getCurrentItem();
pager.removeViewAt(pos);
1
Ragu Ram

Sur la base d’autres réponses et d’autres ressources, j’ai terminé avec ce code.

CustomPagerAdapter:

import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.support.v4.app.FragmentTransaction;
import Android.support.v4.view.PagerAdapter;
import Android.view.View;
import Android.view.ViewGroup;

import Java.util.ArrayList;
import Java.util.HashMap;
import Java.util.List;
import Java.util.Map;

public class CustomPagerAdapter extends PagerAdapter {

  private List<Fragment> pages = new ArrayList<>();
  private Map<Fragment, Integer> fragmentsPosition = new HashMap<>();

  private Fragment currentPrimaryItem;
  private FragmentManager fragmentManager;
  private FragmentTransaction currentTransaction;


  public CustomPagerAdapter(FragmentManager fragmentManager) {
    this.fragmentManager = fragmentManager;
  }

  @Override
  public Object instantiateItem(ViewGroup container, int position) {
    if (currentTransaction == null) {
      currentTransaction = fragmentManager.beginTransaction();
    }

    Fragment pageFragment = pages.get(position);
    String tag = pageFragment.getArguments().getString(MainActivity.FRAGMENT_TAG_ARG);
    Fragment fragment = fragmentManager.findFragmentByTag(tag);

    if (fragment != null) {
      if (fragment.getId() == container.getId()) {
        currentTransaction.attach(fragment);
      }
      else {
        fragmentManager.beginTransaction().remove(fragment).commit();
        fragmentManager.executePendingTransactions();
        currentTransaction.add(container.getId(), fragment, tag);
      }
    }
    else {
      fragment = pageFragment;
      currentTransaction.add(container.getId(), fragment, tag);
    }

    if (fragment != currentPrimaryItem) {
      fragment.setMenuVisibility(false);
      fragment.setUserVisibleHint(false);
    }

    return fragment;
  }

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

  @Override
  public void destroyItem(ViewGroup container, int position, Object object) {
    if (currentTransaction == null) {
      currentTransaction = fragmentManager.beginTransaction();
    }

    currentTransaction.detach((Fragment) object);
  }

  @Override
  public void setPrimaryItem(ViewGroup container, int position, Object object) {
    Fragment fragment = (Fragment) object;

    if (fragment != currentPrimaryItem) {
      if (currentPrimaryItem != null) {
        currentPrimaryItem.setMenuVisibility(false);
        currentPrimaryItem.setUserVisibleHint(false);
      }

      if (fragment != null) {
        fragment.setMenuVisibility(true);
        fragment.setUserVisibleHint(true);
      }

      currentPrimaryItem = fragment;
    }
  }

  @Override
  public void finishUpdate(ViewGroup container) {
    if (currentTransaction != null) {
      currentTransaction.commitAllowingStateLoss();
      currentTransaction = null;
      fragmentManager.executePendingTransactions();
    }
  }

  @Override
  public boolean isViewFromObject(View view, Object object) {
    return ((Fragment) object).getView() == view;
  }

  @Override
  public int getItemPosition(Object o) {
    Integer result = fragmentsPosition.get(o);

    if (result == null) {
      return PagerAdapter.POSITION_UNCHANGED;
    }

    return result;
  }

  // ---------------------------------- Page actions ----------------------------------

  public void addPage(Fragment fragment) {
    fragmentsPosition.clear();
    pages.add(fragment);
    notifyDataSetChanged();
  }

  public void removePage(int position) {
    fragmentsPosition.clear();

    Fragment pageFragment = pages.get(position);
    String tag = pageFragment.getArguments().getString(MainActivity.FRAGMENT_TAG_ARG);

    Fragment fragment = fragmentManager.findFragmentByTag(tag);

    if (fragment != null) {
      fragmentsPosition.put(fragment, PagerAdapter.POSITION_NONE);
    }

    for (int i = position + 1; i < pages.size(); i++) {
      pageFragment = pages.get(i);
      tag = pageFragment.getArguments().getString(MainActivity.FRAGMENT_TAG_ARG);
      fragment = fragmentManager.findFragmentByTag(tag);

      if (fragment != null) {
        fragmentsPosition.put(fragment, i - 1);
      }
    }

    pages.remove(position);
    notifyDataSetChanged();
  }

}

Activité principale:

import Android.os.Bundle;
import Android.support.v4.view.ViewPager;
import Android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

  public static final String FRAGMENT_TAG_ARG = "tag";

  private CustomPagerAdapter mCustomPagerAdapter;

  private ViewPager mViewPager;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mCustomPagerAdapter = new CustomPagerAdapter(getSupportFragmentManager());
    mCustomPagerAdapter.addPage(MainFragment.newInstance("Main_Title"));
    mCustomPagerAdapter.addPage(SecondaryFragment.newInstance("Secondary_Title"));

    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mCustomPagerAdapter);
  }

}

Pour supprimer des pages:

mCustomPagerAdapter.removePage(1);

MainFragment:

import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.TextView;

public class MainFragment extends Fragment {

  public static final String FRAGMENT_TAG = "MainFragment";

  public static MainFragment newInstance(String text) {
    return newInstance(text, FRAGMENT_TAG);
  }

  public static MainFragment newInstance(String text, String tag) {
    MainFragment fragment = new MainFragment();
    Bundle args = new Bundle();
    args.putString("text", text);
    args.putString(MainActivity.FRAGMENT_TAG_ARG, tag + "_" + fragment.hashCode());
    fragment.setArguments(args);
    return fragment;
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_main, container, false);
    TextView textView = (TextView) rootView.findViewById(R.id.section_label);
    textView.setText(getArguments().getString("text"));
    return rootView;
  }

}

SecondaryFragment a le même code.

Les dispositions sont simples: ViewPager/Fragment, avec Android.support.v4.view.ViewPager avec id container et Fragment TextView avec id section_label.

Ressources:

0
mortalis

Cette solution fonctionne bien pour l'instant: 

 public class CustomPagerAdapter extends PagerAdapter {

    private final List<Item> objects = new ArrayList<>();

    public CustomPagerAdapter(List<Item> objects) {
        if (objects != null) {
            this.objects.add(objects);
        }
    }

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

    @Override
    public boolean isViewFromObject(View view, Object object) {
        Item item = (Item) object;
        ItemView itemView = (ItemView) view;
        return Objects.equals(itemView.getItem(), item);
    }

    @Override
    public int getItemPosition(Object object) {
        Item item = (Item) object;
        int idx = objects.indexOf(item);
        return idx == -1 ? POSITION_NONE : idx;
    }

    @Override
    public Item instantiateItem(ViewGroup container, int position) {
        Item item = objects.get(position);

        final int id = generateViewIdForItem(item);
        ItemView itemView = new ItemView(container.getContext());
        itemView.setId(id);
        container.addView(itemView);

        itemView.setItem(item);

        return item;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        Item item = (Item) object;
        final int id = generateViewIdForItem(item);
        View view = container.findViewById(id);
        if (view != null) {
            container.removeView(view);
        }
    }

    public void update(@Nullable List<Item> objects) {
        this.objects.clear();
        if (objects != null) {
            this.objects.addAll(objects);
        }
        notifyDataSetChanged();
    }

    public void clear() {
        update(null);
    }

    /* add remove/update/add methods if you need, don't forget to call notifyDataSetChanged */

    private static int generateViewIdForItem(Item item) {
        return Math.abs(item.hashCode());
    }
}

Notez s'il vous plaît:

  • Votre classe Item doit contenir une implémentation correspondante pour les méthodes equals et hashCode
  • Votre classe ItemView doit contenir getter et setter pour votre objet Item.
0
fraggjkee