165 votes

ajouter et supprimer dynamiquement vue de viewpager

(J'ai trouvé une solution - s'il vous plaît voir mon post dans la section ci-dessous.)

Dans mon application, l'utilisateur de démarrer avec un seul point de vue de ses données. Je voudrais ajouter un ViewPager et de permettre à l'utilisateur d'ajouter plus de vues que désiré. Comment dois-je faire? (Je n'souhaitez utiliser le FragmentPagerAdapter.)

J'ai lu d'innombrables postes et des aperçus, mais je suis toujours en manque de quelque chose. Voici ce que je crois comprendre:

MainActivity crée un ViewPager et PagerAdapter:

ViewPager pager = null;
MainPagerAdapter adapter = null;
public void onCreate (Bundle savedInstanceState)
{
  super.onCreate (savedInstanceState);
  pager = new ViewPager (this);
  setContentView (pager);

  adapter = new MainPagerAdapter();
  pager.setAdapter (adapter); 

  View v0 = code_to_create_initial_view();
  adapter.add (v0, 0);      
}

Utiliser un PagerAdapter de fournir les ensembles de vue. Pour cela, il semble que j'ai besoin de méthodes pour ajouter et supprimer des points de vue, quelque chose comme cela; évidemment, il en faut plus pour raconter l'ViewPager choses a changé et comment montrer le changement:

class MainPagerAdapter extends PagerAdapter
{
  // This holds all the currently displayable views, in order from left to right.
  private ArrayList<View> views = new ArrayList<View>();

  public void addView (View v, int position)
  {
    views.add (position, v);
  }

  public void removeView (int position)
  {
    views.remove (position);
  }
}

En plus, j'ai besoin de mettre en place des méthodes virtuelles. Je suis perdu ici - ce qui les appelle et ce qu'ils sont censés faire (ok, getCount est évident)?

  public object instantiateItem (ViewGroup pager, int position);
  public void destroyItem (ViewGroup, int, Object);
  public int getCount ();
  public boolean isViewFromObject (View, Object);
  • Quelles sont les ViewGroup params pour - n'est-ce pas le groupe contenant le ViewPager lui-même?
  • Ce n'isViewFromObject faire - comment obtenir un objet associé à une vue à la première place?
  • Devrais-je appeler startUpdate et finishUdate lorsque je ajouter ou supprimer des points de vue?

Merci.

282voto

Peri Hartman Points 2617

Après avoir essayer de comprendre ce qui ViewPager méthodes sont appelées par ViewPager et qui sont pour d'autres raisons, je suis venu avec une solution. Je la présente ici car je vois beaucoup de gens qui ont de la difficulté avec cela et je ne vois pas d'autres réponses pertinentes.

Tout d'abord, voici ma carte; j'espère que les commentaires dans le code sont suffisantes:

class MainPagerAdapter extends PagerAdapter
{
  // This holds all the currently displayable views, in order from left to right.
  private ArrayList<View> views = new ArrayList<View>();

  //-----------------------------------------------------------------------------
  // Used by ViewPager.  "Object" represents the page; tell the ViewPager where the
  // page should be displayed, from left-to-right.  If the page no longer exists,
  // return POSITION_NONE.
  @Override
  public int getItemPosition (Object object)
  {
    int index = views.indexOf (object);
    if (index == -1)
      return POSITION_NONE;
    else
      return index;
  }

  //-----------------------------------------------------------------------------
  // Used by ViewPager.  Called when ViewPager needs a page to display; it is our job
  // to add the page to the container, which is normally the ViewPager itself.  Since
  // all our pages are persistent, we simply retrieve it from our "views" ArrayList.
  @Override
  public Object instantiateItem (ViewGroup container, int position)
  {
    View v = views.get (position);
    container.addView (v);
    return v;
  }

  //-----------------------------------------------------------------------------
  // Used by ViewPager.  Called when ViewPager no longer needs a page to display; it
  // is our job to remove the page from the container, which is normally the
  // ViewPager itself.  Since all our pages are persistent, we do nothing to the
  // contents of our "views" ArrayList.
  @Override
  public void destroyItem (ViewGroup container, int position, Object object)
  {
    container.removeView (views.get (position));
  }

  //-----------------------------------------------------------------------------
  // Used by ViewPager; can be used by app as well.
  // Returns the total number of pages that the ViewPage can display.  This must
  // never be 0.
  @Override
  public int getCount ()
  {
    return views.size();
  }

  //-----------------------------------------------------------------------------
  // Used by ViewPager.
  @Override
  public boolean isViewFromObject (View view, Object object)
  {
    return view == object;
  }

  //-----------------------------------------------------------------------------
  // Add "view" to right end of "views".
  // Returns the position of the new view.
  // The app should call this to add pages; not used by ViewPager.
  public int addView (View v)
  {
    return addView (v, views.size());
  }

  //-----------------------------------------------------------------------------
  // Add "view" at "position" to "views".
  // Returns position of new view.
  // The app should call this to add pages; not used by ViewPager.
  public int addView (View v, int position)
  {
    views.add (position, v);
    return position;
  }

  //-----------------------------------------------------------------------------
  // Removes "view" from "views".
  // Retuns position of removed view.
  // The app should call this to remove pages; not used by ViewPager.
  public int removeView (ViewPager pager, View v)
  {
    return removeView (pager, views.indexOf (v));
  }

  //-----------------------------------------------------------------------------
  // Removes the "view" at "position" from "views".
  // Retuns position of removed view.
  // The app should call this to remove pages; not used by ViewPager.
  public int removeView (ViewPager pager, int position)
  {
    // ViewPager doesn't have a delete method; the closest is to set the adapter
    // again.  When doing so, it deletes all its views.  Then we can delete the view
    // from from the adapter and finally set the adapter to the pager again.  Note
    // that we set the adapter to null before removing the view from "views" - that's
    // because while ViewPager deletes all its views, it will call destroyItem which
    // will in turn cause a null pointer ref.
    pager.setAdapter (null);
    views.remove (position);
    pager.setAdapter (this);

    return position;
  }

  //-----------------------------------------------------------------------------
  // Returns the "view" at "position".
  // The app should call this to retrieve a view; not used by ViewPager.
  public View getView (int position)
  {
    return views.get (position);
  }

  // Other relevant methods:

  // finishUpdate - called by the ViewPager - we don't care about what pages the
  // pager is displaying so we don't use this method.
}

Et voici quelques bouts de code montrant comment utiliser la carte.

class MainActivity extends Activity
{
  private ViewPager pager = null;
  private MainPagerAdapter pagerAdapter = null;

  //-----------------------------------------------------------------------------
  @Override
  public void onCreate (Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView (R.layout.main_activity);

    ... do other initialization, such as create an ActionBar ...

    pagerAdapter = new MainPagerAdapter();
    pager = (ViewPager) findViewById (R.id.view_pager);
    pager.setAdapter (pagerAdapter);

    // Create an initial view to display; must be a subclass of FrameLayout.
    FrameLayout v0 = (FrameLayout) inflater.inflate (R.layout.one_of_my_page_layouts, null);
    pagerAdapter.addView (v0, 0);
  }

  //-----------------------------------------------------------------------------
  // Here's what the app should do to add a view to the ViewPager.
  public void addView (View newPage)
  {
    int pageIndex = pagerAdapter.addView (newPage);
    // You might want to make "newPage" the currently displayed page:
    pager.setCurrentItem (pageIndex, true);
  }

  //-----------------------------------------------------------------------------
  // Here's what the app should do to remove a view from the ViewPager.
  public void removeView (View defunctPage)
  {
    int pageIndex = pagerAdapter.removeView (pager, defunctPage);
    // You might want to choose what page to display, if the current page was "defunctPage".
    if (pageIndex == pagerAdapter.getCount())
      pageIndex--;
    pager.setCurrentItem (pageIndex);
  }

  //-----------------------------------------------------------------------------
  // Here's what the app should do to get the currently displayed page.
  public View getCurrentPage ()
  {
    return pagerAdapter.getView (pager.getCurrentItem());
  }

  //-----------------------------------------------------------------------------
  // Here's what the app should do to set the currently displayed page.  "pageToShow" must
  // currently be in the adapter, or this will crash.
  public void setCurrentPage (View pageToShow)
  {
    pager.setCurrentItem (pagerAdapter.getItemPosition (pageToShow), true);
  }
}

Enfin, vous pouvez utiliser les éléments suivants pour votre activité principale disposition:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</android.support.v4.view.ViewPager>

5voto

Roman Truba Points 1195

Je cherchais une solution simple pour retirer les vues de viewpager (pas de fragments) de manière dynamique. Donc, si vous avez des infos, que vos pages appartient, vous pouvez l'Afficher sous forme de tag. Juste comme ça (carte de code):

@Override
public Object instantiateItem(ViewGroup collection, int position)
{
    ImageView iv = new ImageView(mContext);
    MediaMessage msg = mMessages.get(position);
    ...

    iv.setTag(media);
    return iv;
}

@Override
public int getItemPosition (Object object)
{
    View o = (View) object;
    int index = mMessages.indexOf(o.getTag());
    if (index == -1)
        return POSITION_NONE;
    else
        return index;
}

Vous avez juste besoin de supprimer vos informations de mMessages, puis appelez notifyDataSetChanged() pour votre carte. Mauvaise nouvelle, il n'y a pas d'animation dans ce cas.

2voto

thalespf Points 186

Voici une solution alternative à cette question. Ma carte:

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 pour supprimer et ajouter de manière dynamique

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

pagerAdapter.addPage(pass your fragment);

Après avis de la Péri Hartman, il a commencé à travailler, après j'ai mis nul ne ViewPager de l'adaptateur et de mettre la carte à nouveau après le point de vue supprimé. Avant cela, la page 0 ne marche pas montré son contenu de la liste.

Merci.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X