Depois de descobrir quais métodos do ViewPager são chamados pelo ViewPager e quais são para outros fins, criei uma solução. Eu a apresento aqui, pois vejo muitas pessoas lutando com isso e não vi outras respostas relevantes.
Primeiro, aqui está o meu adaptador; espero que comentários dentro do código sejam suficientes:
public 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.
}
E aqui estão alguns trechos de código que mostram como usar o adaptador.
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.
LayoutInflater inflater = context.getLayoutInflater();
FrameLayout v0 = (FrameLayout) inflater.inflate (R.layout.one_of_my_page_layouts, null);
pagerAdapter.addView (v0, 0);
pagerAdapter.notifyDataSetChanged();
}
//-----------------------------------------------------------------------------
// 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);
}
}
Por fim, você pode usar o seguinte para seu activity_main.xml
layout:
<?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>
Eu estava procurando uma solução simples para remover visualizações do viewpager (sem fragmentos) dinamicamente. Portanto, se você tiver algumas informações às quais suas páginas pertencem, defina-as como Exibir como tag. Assim (código do adaptador):
Você só precisa remover suas informações do mMessages e ligar
notifyDataSetChanged()
para o seu adaptador. Más notícias: não há animação neste caso.fonte
Existem algumas discussões sobre esse tópico
Embora o vejamos com frequência, o uso
POSITION_NONE
não parece ser o caminho a seguir, pois é muito ineficiente em termos de memória.Aqui nesta pergunta, devemos considerar o uso da abordagem de Alvaro :
Aqui está uma resposta SO com código baseado nessa ideia
fonte
Eu fiz um programa semelhante. Espero que isso ajude você. Em sua primeira atividade, quatro dados de grade podem ser selecionados. Na próxima atividade, há um pager de exibição que contém duas páginas obrigatórias e mais quatro páginas estarão lá, que serão visíveis correspondentes aos dados da grade selecionados.
A seguir, é apresentada a principal atividade MainActivity
Aqui TabFragment1, TabFragment2 etc são fragmentos a serem exibidos no viewpager. E não estou mostrando os layouts, pois estão fora do escopo deste projeto.
MainActivity terá a intenção de Main2Activity Main2Activity
ViewPagerAdapter Viewpageradapter.class
Layout para main2activity acticity_main2.xml
Espero que isso ajude alguém ... Clique no botão, por favor, se isso ajudou você
fonte
Aqui está uma solução alternativa para esta pergunta. Meu adaptador:
Código para remover e adicionar dinamicamente
Após o conselho de Peri Hartman, ele começou a funcionar depois de eu definir o adaptador null do ViewPager e colocá-lo novamente após a remoção das visualizações. Antes disso, a página 0 não mostrava o conteúdo da lista.
Obrigado.
fonte
Eu criei uma biblioteca personalizada do PagerAdapters para alterar itens no PagerAdapters dinamicamente.
Você pode alterar itens dinamicamente, como segue, usando esta biblioteca.
A biblioteca Thils também suporta páginas criadas por Fragments.
fonte
Para remover, você pode usar isso diretamente:
fragment
é o fragmento que você deseja remover.fonte
Acho uma boa solução para esse problema, essa solução pode fazê-lo funcionar e não há necessidade de recriar fragmentos.
Meu ponto principal é:
Código fonte
O código está no meu Github Gist .
fonte