A resposta principal depende de um nome que está sendo gerado pela estrutura. Se isso mudar, não funcionará mais.
Que tal esta solução, substituindo instantiateItem()
e destroyItem()
sua Fragment(State)PagerAdapter
:
public class MyPagerAdapter extends FragmentStatePagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return ...;
}
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(...);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
Isso parece funcionar para mim ao lidar com fragmentos que estão disponíveis. Fragmentos que ainda não foram instanciados retornarão nulos ao chamar getRegisteredFragment
. Mas eu tenho usado isso principalmente para obter a corrente Fragment
do ViewPager
: adapater.getRegisteredFragment(viewPager.getCurrentItem())
e isso não retornará null
.
Não conheço outras desvantagens dessa solução. Se houver, eu gostaria de saber.
Fragment
em umWeakReference
para garantir que você não impedem que um fragmento destruída de ser lixo coletado? Apenas parece que a coisa certa a fazer ...MyPagerAdapter
é destruído devido ao ciclo de vida (ou seja, girar), nãoregisterdFragments
será perdido? OActivity
/Fragment
usingMyPagerAdapter
precisará salvá-loonSaveInstanceState
e precisará atualizá-lo com a novaFragmentManager
ref?getItem
não é chamado novamente ao rodar (para quaisquer frags que já foram criados), poisFragmentManager
restaura os estados doFragments
mesmo no pager. E seinstantiateItem
for chamado quando cada umFragment
for restaurado, essa solução será de fato mais segura e mais futura do que a minha ou a resposta aceita. Vou considerar tentar isso sozinho.Para pegar fragmentos de um ViewPager, existem muitas respostas aqui e em outros tópicos / blogs relacionados ao SO. Todo mundo que eu vi está quebrado, e eles geralmente parecem se encaixar em um dos dois tipos listados abaixo. Existem outras soluções válidas se você quiser apenas pegar o fragmento atual, como esta outra resposta neste tópico.
Se estiver usando
FragmentPagerAdapter
veja abaixo. Se usar oFragmentStatePagerAdapter
seu vale a pena olhar para isso . Os índices de captura que não são os atuais em um FragmentStateAdapter não são tão úteis quanto, por natureza, serão completamente reduzidos e ficaram fora de vista / fora dos limites offScreenLimit.OS CAMINHOS INFELIZES
Errado: mantenha sua própria lista interna de fragmentos, adicionada a quando
FragmentPagerAdapter.getItem()
é chamadaSparseArray
ouMap
getItem
é chamado apenas na primeira vez em que uma página é rolada para (ou obtida se seuViewPager.setOffscreenPageLimit(x)
> 0) noViewPager
, se o hostActivity
/Fragment
for interrompida ou reiniciada, o internoSpaseArray
será eliminado quando o FragmentPagerActivity personalizado for recriado, mas nos bastidores o ViewPagers fragmentos internos vai ser recriada egetItem
vai NÃO ser chamado para qualquer um dos índices, de modo a capacidade de obter um fragmento de índice será perdido para sempre. Você pode explicar isso salvando e restaurando essas referências de fragmentos viaFragmentManager.getFragment()
e,putFragment
mas isso começa a ficar IMHO bagunçado.Errado: construa seu próprio ID de tag correspondente ao que é usado sob o capô no
FragmentPagerAdapter
e use-o para recuperar os fragmentos de página doFragmentManager
ViewPager
que poderia alterar a qualquer momento ou para qualquer versão do sistema operacional.O método recriado para esta solução é
UM CAMINHO FELIZ:
ViewPager.instantiateItem()
Uma abordagem semelhante à
getItem()
anterior, mas que não interrompe o ciclo de vida, é a de conectar-seinstantiateItem()
invés degetItem()
como o primeiro será chamado toda vez que o índice for criado / acessado. Veja esta respostaUM CAMINHO FELIZ: Construa seu próprio
FragmentViewPager
Construa sua própria
FragmentViewPager
classe a partir da fonte da última lib de suporte e altere o método usado internamente para gerar as tags de fragmento. Você pode substituí-lo pelo abaixo. Isso tem a vantagem de que você sabe que a criação da tag nunca será alterada e que você não depende de uma API / método particular, o que é sempre perigoso.Então, como o documento diz, quando você quiser pegar um fragmento usado para um índice, chame algo como este método (que você pode colocar no costume
FragmentPagerAdapter
ou em uma subclasse) sabendo que o resultado pode ser nulo se getItem ainda não foi chamado. essa página, ou seja, ainda não foi criada.Esta é uma solução simples e resolve os problemas das outras duas soluções encontradas em todos os lugares na Web
fonte
instantiateItem()
quando você deseja acessar um fragmento que ainda não foi visitado após a ocorrência de um evento do ciclo de vida e foi visitado antes do evento do ciclo de vida. Uma pequena diferença que eu conheço, mas que levou a um bug sutil no meu programa, portanto, eu estou investigando isso.getItemId(pos)
interiorFragmentStatePagerAdapter
Adicione os próximos métodos ao seu FragmentPagerAdapter:
getActiveFragment (0) tem que funcionar.
Aqui está a solução implementada no ViewPager https://gist.github.com/jacek-marchwicki/d6320ba9a910c514424d . Se algo falhar, você verá um bom log de falha.
fonte
Outra solução simples:
fonte
setPrimaryItem()
é chamado depoisViewPager.OnPageChangeListener#onPageSelected()
eu não posso usá-lo :-(Eu sei que isso tem algumas respostas, mas talvez isso ajude alguém. Eu tenho usado uma solução relativamente simples quando eu precisava para obter um
Fragment
do meuViewPager
. No seuActivity
ouFragment
segurando oViewPager
, você pode usar esse código para percorrer cadaFragment
um deles.Se você souber a sua posição
Fragment
noViewPager
, você pode simplesmente ligargetItem(knownPosition)
.Se você não sabe a sua posição
Fragment
noViewPager
, você pode fazer com que seus filhosFragments
implementem uma interface com um método como essegetUniqueId()
e use isso para diferenciá-los. Ou você pode percorrer tudoFragments
e verificar o tipo de classe, comoif(viewPagerFragment instanceof FragmentClassYouWant)
!!! EDIT !!!
Eu descobri que
getItem
só é chamado porFragmentPagerAdapter
quando cada umFragment
precisa ser criado na primeira vez , depois disso, parece que oFragments
são reciclados usando oFragmentManager
. Dessa forma, muitas implementações deFragmentPagerAdapter
criação de novosFragment
sgetItem
. Usando o meu método acima, isso significa que criaremos novosFragment
s cada vez quegetItem
for chamado à medida que passarmos por todos os itens noFragmentPagerAdapter
. Devido a isso, eu encontrei uma abordagem melhor, usando oFragmentManager
para obter cada umFragment
(usando a resposta aceita). Esta é uma solução mais completa e está funcionando bem para mim.E você precisará deste método.
fonte
ViewPager
próprio define essas tags. Esta solução é frágil porque depende do conhecimento da convenção de nomenclatura "oculta" doViewPager
. A resposta do Streets of Boston é uma solução muito mais abrangente, que agora uso no meu projeto (em vez dessa abordagem).Para o meu caso, nenhuma das soluções acima funcionou.
No entanto, como estou usando o Gerenciador de fragmentos filho em um fragmento, o seguinte foi usado:
Fragment f = getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());
Isso funcionará apenas se seus fragmentos no Gerenciador corresponderem ao item do viewpager.
fonte
fonte
Eu lidei com isso primeiro fazendo uma lista de todos os fragmentos (
List<Fragment> fragments;
) que eu iria usar e os adicionei ao pager, facilitando o manuseio do fragmento atualmente exibido.Assim:
então isso pode ser chamado:
então eu poderia jogá-lo em uma instrução if que só seria executada se estivesse no fragmento correto
mas essa é apenas a minha abordagem de hack e slash, mas funcionou para mim; eu a uso para fazer alterações relevantes no fragmento exibido no momento quando o botão Voltar é pressionado.
fonte
Isso é baseado na resposta de Steven acima. Isso retornará a instância real do fragmento que já está anexado à atividade pai.
fonte
Não consegui encontrar uma maneira simples e limpa de fazer isso. No entanto, o widget ViewPager é apenas outro ViewGroup, que hospeda seus fragmentos. O ViewPager possui esses fragmentos como filhos imediatos. Portanto, você pode iterar sobre eles (usando .getChildCount () e .getChildAt ()) e ver se a instância de fragmento que você está procurando está atualmente carregada no ViewPager e obter uma referência a ela. Por exemplo, você pode usar algum campo de ID exclusivo estático para diferenciar os fragmentos.
Observe que o ViewPager pode não ter carregado o fragmento que você está procurando, pois é um contêiner de virtualização como o ListView.
fonte
FragmentPagerAdapter é a fábrica dos fragmentos. Para encontrar um fragmento com base em sua posição, se ainda estiver na memória, use isto:
Código de amostra para a API de suporte da v4.
fonte
Você não precisa chamar
getItem()
ou algum outro método posteriormente para obter a referência de umFragment
host hospedadoViewPager
. Se você deseja atualizar alguns dados internosFragment
, use esta abordagem: Atualizar o ViewPager dinamicamente?A chave é definir novos dados dentro
Adaper
e chamar,notifyDataSetChanged()
que por sua vez chamarágetItemPosition()
, passando uma referência suaFragment
e dando a você a chance de atualizá-la. Todas as outras formas exigem que você mantenha referência a si mesmo ou a algum outro truque, o que não é uma boa solução.fonte
getItemPosition()
é um método no seu adaptador. Você não vai ligar diretamente. Você tem uma referência do seu adaptador, paraadapter.notifyDataSetChanged()
ligar e ligargetItemPosition()
para o seu adaptador, passando a referência dos seusFragment
s. Você pode ver uma implementação completa em ação aqui stackoverflow.com/questions/19891828/…Fragment
mas como obter uma referência é passível de debate. Outras soluções obter referência deFragmentManager
usar uma corda semelhante a"android:switcher:"+id
ou retornandoPOSITION_NONE
degetItemosition()
causando todos os fragmentos para recriar-se.Deve se estender
FragmentPagerAdapter
à sua classe de adaptador do ViewPager.Se você usar
FragmentStatePagerAdapter
, não poderá encontrar o seuFragment
pelo seuID
Como usar este método: -
fonte
Ei, eu respondi a esta pergunta aqui . Basicamente, você precisa substituir
método de FragmentStatePagerAdapter.
fonte
A melhor solução é usar a extensão que criamos no CodePath chamada SmartFragmentStatePagerAdapter . Seguindo esse guia, isso facilita a recuperação de fragmentos e do fragmento atualmente selecionado de um ViewPager. Ele também faz um trabalho melhor de gerenciar a memória dos fragmentos incorporados no adaptador.
fonte
A maneira mais fácil e concisa. Se todos os seus fragmentos
ViewPager
forem de classes diferentes, você poderá recuperá-los e diferenciá-los da seguinte maneira:fonte
Eu implementei isso facilmente com uma abordagem um pouco diferente.
Meu método FragmentAdapter.getItem personalizado não retornou novo MyFragment (), mas a instância de MyFragment que foi criada no construtor FragmentAdapter.
Na minha atividade, obtive o fragmento do adaptador, verifique se ele é instanceOf needed Fragment e, em seguida, projete e use os métodos necessários.
fonte
Crie um ID de recurso inteiro em /values/integers.xml
Em seguida, na função getItem do PagerAdapter:
Em atividade, escreva esta função para obter uma referência de fragmento:
Obtenha a referência do fragmento chamando a função acima e, em seguida, faça a conversão no seu fragmento personalizado:
fonte
Maneira fácil de iterar sobre fragmentos no gerenciador de fragmentos. Localize o viewpager, que possui argumento de posição de seção, colocado em público estático PlaceholderFragment newInstance (int sectionNumber) .
fonte
Em Fragmento
Em FragmentActivity
fonte
No TabLayout, existem várias guias para Fragment. você pode encontrar o fragmento por Tag usando o índice do fragmento.
Por ex. o índice para o fragmento1 é 0, portanto, no
findFragmentByTag()
método, passe a tag para o Viewpager.after usando fragmentTransaction que você pode adicionar, substitua o fragmento.String tag = "android:switcher:" + R.id.viewPager + ":" + 0; Fragment1 f = (Fragment1) getSupportFragmentManager().findFragmentByTag(tag);
fonte
Ok para o adaptador
FragmentStatePagerAdapter
, financio uma solução:em seu FragmentActivity:
e crie um método na sua classe FragmentActivity - para que esse método lhe dê acesso ao seu fragmento, você só precisa fornecer a posição do fragmento que deseja:
no seu adaptador:
fonte
index
é o lugar do fragmento no adaptador como você adicionoufragment1
primeiro, então volte afragment1
passarindex
como 0 e assim por diantefonte