Estou usando o ViewPager de compatibilidade com a v4 no Android. My FragmentActivity possui um monte de dados que devem ser exibidos de maneiras diferentes em páginas diferentes no meu ViewPager. Até agora, tenho apenas 3 instâncias do mesmo ListFragment, mas no futuro terei 3 instâncias de ListFragments diferentes. O ViewPager está em uma tela vertical do telefone, as listas não estão lado a lado.
Agora, um botão no ListFragment inicia uma atividade de página inteira separada (via FragmentActivity), que retorna e FragmentActivity modifica os dados, salva-os e tenta atualizar todas as visualizações no ViewPager. É aqui, onde estou preso.
public class ProgressMainActivity extends FragmentActivity
{
MyAdapter mAdapter;
ViewPager mPager;
@Override
public void onCreate(Bundle savedInstanceState)
{
...
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.viewpager);
mPager.setAdapter(mAdapter);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
...
updateFragments();
...
}
public void updateFragments()
{
//Attempt 1:
//mAdapter.notifyDataSetChanged();
//mPager.setAdapter(mAdapter);
//Attempt 2:
//HomeListFragment fragment = (HomeListFragment) getSupportFragmentManager().findFragmentById(mAdapter.fragId[0]);
//fragment.updateDisplay();
}
public static class MyAdapter extends FragmentPagerAdapter implements
TitleProvider
{
int[] fragId = {0,0,0,0,0};
public MyAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public String getTitle(int position){
return titles[position];
}
@Override
public int getCount(){
return titles.length;
}
@Override
public Fragment getItem(int position)
{
Fragment frag = HomeListFragment.newInstance(position);
//Attempt 2:
//fragId[position] = frag.getId();
return frag;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE; //To make notifyDataSetChanged() do something
}
}
public class HomeListFragment extends ListFragment
{
...
public static HomeListFragment newInstance(int num)
{
HomeListFragment f = new HomeListFragment();
...
return f;
}
...
Agora, como você pode ver, minha primeira tentativa foi notificar DataSetChanged em todo o FragmentPagerAdapter, e isso mostrou atualizar os dados algumas vezes, mas em outras eu recebi uma IllegalStateException: Não é possível executar esta ação após onSaveInstanceState.
Minha segunda tentativa envolveu tentar chamar uma função de atualização em meu ListFragment, mas getId em getItem retornou 0. Conforme os documentos que eu tentei
adquirindo uma referência ao Fragmento de FragmentManager, usando findFragmentById () ou findFragmentByTag ()
mas não sei a etiqueta ou o id dos meus fragmentos! Eu tenho um andróide: id = "@ + id / viewpager" para o ViewPager e um andróide: id = "@ android: id / list" para o meu ListView no layout ListFragment, mas não acho que sejam úteis.
Portanto, como posso: a) atualizar o ViewPager inteiro com segurança de uma só vez (o ideal é retornar o usuário à página em que ele estava antes) - tudo bem que o usuário veja a exibição mudar. Ou, de preferência, b) chame uma função em cada ListFragment afetado para atualizar o ListView manualmente.
Qualquer ajuda seria aceita com gratidão!
null
por fragmento.FragmentPagerAdaper
mas não paraFragmentStatePagerAdaper
(Fragment.getTag()
sempre voltarnull
.A resposta de Barkside funciona,
FragmentPagerAdapter
mas não funcionaFragmentStatePagerAdapter
, porque não define tags nos fragmentos para os quais passaFragmentManager
.Com
FragmentStatePagerAdapter
parece que nós podemos obter, utilizando a suainstantiateItem(ViewGroup container, int position)
chamada. Retorna a referência ao fragmento na posiçãoposition
. SeFragmentStatePagerAdapter
já possui referência ao fragmento em questão,instantiateItem
apenas retorna a referência a esse fragmento e não chamagetItem()
para instancia-lo novamente.Então, suponha, atualmente estou vendo o fragmento 50 e quero acessar o fragmento 49. Como eles estão próximos, há uma boa chance de o # 49 já ser instanciado. Assim,
fonte
FragmentStatePagerAdapter
, usar o código acima coma.instantiateItem(viewPager, viewPager.getCurrentItem());
(para se livrar dos 49) como proposto por @ mblackwell8 funciona perfeitamente.instantiateItem
devem ser cercadas porstartUpdate
/finishUpdate
calls. detalhes estão na minha resposta a uma pergunta semelhante: stackoverflow.com/questions/14035090/...OK, acho que encontrei uma maneira de executar a solicitação b) em minha própria pergunta, para compartilhar em benefício dos outros. A tag de fragmentos dentro de um ViewPager está no formulário
"android:switcher:VIEWPAGER_ID:INDEX"
, ondeVIEWPAGER_ID
está oR.id.viewpager
layout XML, e INDEX é a posição no viewpager. Portanto, se a posição for conhecida (por exemplo, 0), posso executarupdateFragments()
:Não tenho idéia se essa é uma maneira válida de fazê-lo, mas funcionará até que algo melhor seja sugerido.
fonte
makeFragmentName
usado para gerar o Tag que você poderia usar para uma abordagem um pouco menos hacky:HomeListFragment fragment = (HomeListFragment) getSupportFragmentManager().findFragmentByTag(FragmentPagerAdapter.makeFragmentName(R.id.viewpager, 0));
makeFragmentName
é oprivate static
método, então você não pode ter acesso a ele.Se você me perguntar, a segunda solução na página abaixo, acompanhando todas as páginas de fragmentos "ativas", é melhor: http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part -ii.html
A resposta do barkside é muito hacky para mim.
você acompanha todas as páginas de fragmentos "ativas". Nesse caso, você acompanha as páginas do fragmento no FragmentStatePagerAdapter, usado pelo ViewPager.
Para evitar manter uma referência a páginas de fragmento "inativas", precisamos implementar o método destroyItem (...) do FragmentStatePagerAdapter:
... e quando você precisar acessar a página visível no momento, ligue para:
... onde o método getFragment (int) do MyAdapter se parece com o seguinte:
"
fonte
Ok, depois de testar o método pelo @barkside acima, não consegui fazê-lo funcionar com meu aplicativo. Lembrei-me de que o aplicativo IOSched2012 também usa um
viewpager
, e foi aí que encontrei minha solução. Ele não usa nenhum ID ou Tags de fragmento, pois eles não são armazenados deviewpager
maneira facilmente acessível.Aqui estão as partes importantes dos aplicativos iOS HomeActivity. Preste atenção especial ao comentário , pois é a chave:
E armazene instâncias suas
Fragments
da seguinteFragmentPagerAdapter
maneira:Além disso, lembre-se de proteger suas
Fragment
chamadas da seguinte maneira:fonte
getItem()
não ser chamado depois que o pai for recriado devido a uma alteração no ciclo de vida. Consulte stackoverflow.com/a/24662049/236743 . No exemplo presente é parcialmente protegida contra por um fragmento, mas não os outros doisVocê pode copiar
FragmentPagerAdapter
e modificar algum código fonte, adicionargetTag()
métodopor exemplo
depois estenda-o, substitua esse método abstrato, não precisa ter medo da alteração do grupo Android
FragmentPageAdapter
código fonte no futurofonte
Também funciona sem problemas:
em algum lugar no layout do fragmento de página:
no onCreateView () do fragmento:
e método para retornar Fragment do ViewPager, se existir:
fonte
Como alternativa, você pode substituir o
setPrimaryItem
método da seguinteFragmentPagerAdapter
maneira:fonte
Quero dar a minha abordagem, caso possa ajudar mais alguém:
Este é o meu adaptador de pager:
Na minha atividade eu tenho:
Então, para obter o fragmento atual, o que faço é:
fonte
Esta é a minha solução, pois não preciso acompanhar minhas guias e preciso atualizá-las de qualquer maneira.
fonte