I'm redoing the navigation of an application so that it works as follows: the application consists of a single activity that initially displays a ViewPager
with three views (fragments), and in one of the views there is a button that replaces those fragments for two new fragments.
I found in this SO response that I can not use FragmentPagerAdapter
because it never destroys a fragment after displaying it by first time; since I want to change the fragments, I have to use FragmentStatePagerAdapter
taking care to always return a new fragment instance in the getItem(int position)
method. But for ViewPager
to effectively update the views on display after changing the adapter associated with it (I do not actually change the adapter ), I only change the associated data to it, which I use to instantiate the fragments), I should override the getItemPosition(Object object)
method so that it returns POSITION_NONE
and call notifyDataSetChanged()
in the adapter . However, this is not making the views up-to-date (and that's just my problem).
Follow my code:
ConfigurationItemDoViewPager.java:
public static class ConfiguracoesDeItemDoViewPager {
private String nomeDaAba;
private Class<? extends FragmentoBase> classeDoFragmento;
private Bundle argumentosDoFragmento;
public ConfiguracoesDeItemDoViewPager(String nomeDaAba, Class<? extends FragmentoBase> classeDoFragmento, Bundle argumentosDoFragmento) {
this.nomeDaAba = nomeDaAba;
this.classeDoFragmento = classeDoFragmento;
this.argumentosDoFragmento = argumentosDoFragmento;
}
public String getNomeDaAba() {
return nomeDaAba;
}
public void setNomeDaAba(String nomeDaAba) {
this.nomeDaAba = nomeDaAba;
}
public Class<? extends FragmentoBase> getClasseDoFragmento() {
return classeDoFragmento;
}
public void setClasseDoFragmento(
Class<? extends FragmentoBase> classeDoFragmento) {
this.classeDoFragmento = classeDoFragmento;
}
public Bundle getArgumentosDoFragmento() {
return argumentosDoFragmento;
}
public void setArgumentosDoFragmento(Bundle argumentosDoFragmento) {
this.argumentosDoFragmento = argumentosDoFragmento;
}
}
Constants.java:
public class Constantes {
public static final ConfiguracoesDeItemDoViewPager [] CONFIGURACOES_DO_VIEWPAGER_1;
public static final ConfiguracoesDeItemDoViewPager [] CONFIGURACOES_DO_VIEWPAGER_2;
// Bloco de inicialização de valores estáticos
static {
CONFIGURACOES_DO_VIEWPAGER_1 = new DadosDeItemDoViewPager[3];
CONFIGURACOES_DO_VIEWPAGER_1[0] = new DadosDeItemDoViewPager("Aba 1", FragmentoA.class, null);
CONFIGURACOES_DO_VIEWPAGER_1[1] = new DadosDeItemDoViewPager("Aba 2", FragmentoB.class, null);
CONFIGURACOES_DO_VIEWPAGER_1[2] = new DadosDeItemDoViewPager("Aba 3", FragmentoC.class, null);
CONFIGURACOES_DO_VIEWPAGER_2 = new DadosDeItemDoViewPager[2];
CONFIGURACOES_DO_VIEWPAGER_2[0] = new DadosDeItemDoViewPager("Aba 1", FragmentoD.class, null);
CONFIGURACOES_DO_VIEWPAGER_2[1] = new DadosDeItemDoViewPager("Aba 2", FragmentoE.class, null);
}
...
}
Main.java Activity:
public class AtividadePrincipal extends ActionBarActivity {
private ViewPager mViewPager;
private TabsPagerAdapter mTabsPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTabsPagerAdapter = new TabsPagerAdapter(getSupportFragmentManager(), Constantes.CONFIGURACOES_DO_VIEWPAGER_1);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mTabsPagerAdapter);
}
public void exibirViewPager2() {
((TabsPagerAdapter)mViewPager.getAdapter()).setConfiguracoesParaInicializarViewPager(Constantes.CONFIGURACOES_DO_VIEWPAGER_2);
}
public class TabsPagerAdapter extends FragmentStatePagerAdapter {
private FragmentManager mFragmentManager;
private ConfiguracoesDeItemDoViewPager [] mConfiguracoesDeItensDoViewPager;
public TabsPagerAdapter(FragmentManager fm, ConfiguracoesDeItensDoViewPager [] configuracoesDeItensDoViewPager) {
super(fm);
this.mFragmentManager = fm;
this.mConfiguracoesDeItensDoViewPager = configuracoesDeItensDoViewPager;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public Fragment getItem(int indice) {
Fragment fragmento = null;
try {
fragmento = mConfiguracoesDeItensDoViewPager[indice].getClasseDoFragmento().newInstance();
if (mConfiguracoesDeItensDoViewPager[indice].getArgumentosDoFragmento() != null) {
fragmento.setArguments(mConfiguracoesDeItensDoViewPager[indice].getArgumentosDoFragmento());
}
} catch (IllegalAccessException e) {
Log.e(Logs.gerarTagParaFiltragemNoLogCat(AtividadePrincipal.this, this), "Exceção inesperada!", e);
} catch (InstantiationException e) {
Log.e(Logs.gerarTagParaFiltragemNoLogCat(AtividadePrincipal.this, this), "Exceção inesperada!", e);
}
return fragmento;
}
@Override
public int getCount() {
return mConfiguracoesDeItensDoViewPager.length;
}
@Override
public CharSequence getPageTitle(int posicao) {
return mConfiguracoesDeItensDoViewPager[posicao].getNomeDaAba();
}
public void setConfiguracoesParaInicializarViewPager(ConfiguracoesDeItemDoViewPager [] configuracoes) {
// Remove um fragmento extra contido dentro do FragmentoB, que se for
// deixado no FragmentManager causa erro de id duplicado
FragmentTransaction ft = mFragmentManager.beginTransaction();
Fragment fragmento = mFragmentManager.findFragmentById(R.id.mapa);
if (fragmento != null && fragmento instanceof SupportMapFragment) {
ft.remove(fragmento);
}
ft.commit();
this.mConfiguracoesDeItensDoViewPager = configuracoes;
notifyDataSetChanged();
}
}
}
Just to complete the explanation, when the user clicks a button on one of the fragments, the AtividadePrincipal.exibirViewPager2()
method is called that should update the views / fragments of ViewPager
.
Note: I also asked in SOen .