Recuperar um fragmento de um ViewPager

248

Estou usando um ViewPagerjunto com um FragmentStatePagerAdapterpara hospedar três fragmentos diferentes:

  • [Fragmento1]
  • [Fragmento2]
  • [Fragmento3]

Quando eu quiser começar Fragment1a partir do ViewPagerno FragmentActivity.

Qual é o problema e como corrigi-lo?

Qun Qin
fonte

Respostas:

504

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 Fragmentdo 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.

Ruas de Boston
fonte
41
Esta é a melhor solução em que posso pensar também. Apenas sugestão seria talvez envolva o Fragmentem um WeakReferencepara garantir que você não impedem que um fragmento destruída de ser lixo coletado? Apenas parece que a coisa certa a fazer ...
Alex Lockwood
7
O que acontece quando MyPagerAdapteré destruído devido ao ciclo de vida (ou seja, girar), não registerdFragmentsserá perdido? OActivity / Fragmentusing MyPagerAdapterprecisará salvá-lo onSaveInstanceStatee precisará atualizá-lo com a nova FragmentManagerref?
Steven Byle
10
Se não me engano (e você deve verificar isso), o método getItem não é chamado - como você sabe -, mas o método instantiateItem é chamado para todos os Fragmentos que estão sendo restaurados pela estrutura após uma rotação.
Streets Of Boston
6
Sim, verifiquei que getItemnão é chamado novamente ao rodar (para quaisquer frags que já foram criados), pois FragmentManagerrestaura os estados do Fragmentsmesmo no pager. E seinstantiateItem for chamado quando cada um Fragmentfor 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.
Steven Byle
6
@Ori Eu não quebre. Minha solução não está usando o resultado da chamada 'getItem ()'. Em vez disso, está usando o resultado armazenado da chamada 'instantiateItem ()'. E o ciclo de vida do fragmento não é interrompido, porque o fragmento armazenado será removido da matriz esparsa na chamada 'destroyItem ()'.
Streets Of Boston
85

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 o FragmentStatePagerAdapterseu 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()é chamada

  • Geralmente, usando um SparseArrayouMap
  • Nenhum dos muitos exemplos que vi foram responsáveis ​​por eventos do ciclo de vida, portanto, esta solução é frágil. Como getItemé chamado apenas na primeira vez em que uma página é rolada para (ou obtida se seu ViewPager.setOffscreenPageLimit(x)> 0) no ViewPager, se o host Activity/Fragment for interrompida ou reiniciada, o interno SpaseArrayserá eliminado quando o FragmentPagerActivity personalizado for recriado, mas nos bastidores o ViewPagers fragmentos internos vai ser recriada e getItemvai 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 via FragmentManager.getFragment()e, putFragmentmas 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

  • Isso é melhor na medida em que lida com o problema de referências a fragmentos perdidos na primeira solução de matriz interna, mas, como corretamente apontado nas respostas acima e em outras partes da rede - ele parece um pouco invasivo. privado método interno ao ViewPagerque poderia alterar a qualquer momento ou para qualquer versão do sistema operacional.

O método recriado para esta solução é

private static String makeFragmentName(int viewId, long id) {
    return "android:switcher:" + viewId + ":" + id;
}

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 resposta

UM CAMINHO FELIZ: Construa seu próprio FragmentViewPager

Construa sua própria FragmentViewPagerclasse 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.

/**
 * @param containerViewId the ViewPager this adapter is being supplied to
 * @param id pass in getItemId(position) as this is whats used internally in this class
 * @return the tag used for this pages fragment
 */
public static String makeFragmentName(int containerViewId, long id) {
    return "android:switcher:" + containerViewId + ":" + id;
}

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 FragmentPagerAdapterou 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.

/**
 * @return may return null if the fragment has not been instantiated yet for that position - this depends on if the fragment has been viewed
 * yet OR is a sibling covered by {@link android.support.v4.view.ViewPager#setOffscreenPageLimit(int)}. Can use this to call methods on
 * the current positions fragment.
 */
public @Nullable Fragment getFragmentForPosition(int position)
{
    String tag = makeFragmentName(mViewPager.getId(), getItemId(position));
    Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
    return fragment;
}

Esta é uma solução simples e resolve os problemas das outras duas soluções encontradas em todos os lugares na Web

Dori
fonte
6
Isso funcionará, mas requer a cópia da classe ViewPager no seu próprio código-fonte. Contar com 'instantiateItem ()' e 'destroyItem ()' do adaptador de pager do ViewPager funcionará e honrará os ciclos de vida dos fragmentos (esses 2 métodos também são chamados quando fragmentos são criados a partir de um estado de instância salvo). Você está certo, que confiar em 'getItem ()' sendo chamado não é uma boa ideia e usar APIs privadas também não é.
Streets Of Boston
+1 Eu concordo que também é uma solução e editei acima. A única diferença é que o procedimento acima funciona em mais um caso de uso, 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.
Dori
Se setOffscreenPageLimit = 1 (padrão), o FragmentStatePageAdapter começará a trocar fragmentos dentro e fora da memória à medida que as páginas de exibição forem acessadas. Por uma chamada para getItem (), uma nova instância de páginas / fragmentos revisitados será criada. Após essa revisão, existe uma maneira de instruir o sistema a retomar instâncias criadas anteriormente, em vez de criar uma nova?
carl
se estiver fora do limite da página, será necessário criar um novo - mas passando no estado salvo. Se querendo manter os antigos redor, então você pode aumentar o limite de páginas
Dori
@Dori não há getItemId(pos)interiorFragmentStatePagerAdapter
Jemshit Iskenderov 25/03
70

Adicione os próximos métodos ao seu FragmentPagerAdapter:

public Fragment getActiveFragment(ViewPager container, int position) {
String name = makeFragmentName(container.getId(), position);
return  mFragmentManager.findFragmentByTag(name);
}

private static String makeFragmentName(int viewId, int index) {
    return "android:switcher:" + viewId + ":" + index;
}

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.

kzotin
fonte
Muito obrigado:) . Através dele, espalhei-o de outra maneira, usando um manipulador para postar o fragmento. Isso não é muito adequado, mas acabou com o problema. By the way, você é agradável :)
Qun Qin
12
Eu estava usando esse método, mas acredito que ele parou de funcionar quando mudei para a API 17 (?). Eu recomendaria outro método e preferiria que o Google simplesmente publicasse uma API para recuperar um fragmento de um ViewPager, dada sua posição.
Gcl1
Eu tenho problema Whit chamando o segundo fragmento, o método de criar um novo
Vasil Valchev
2
Como algum método makeFragmentName da versão da API foi alterado para String estática privada makeFragmentName (int viewId, long id) {return "android: switcher:" + viewId + ":" + id; } então o método getActiveFragment agora deve ficar assim (use getItemId em vez de position para o segundo argumento) public Fragment getActiveFragment (container ViewPager, int position) {String name = makeFragmentName (container.getId (), getItemId (position)); retornar mFragmentManager.findFragmentByTag (nome); }
Eugene Popovich
1
Realmente funciona, mas é realmente perigoso, porque depende da implementação interna do pager de exibição e se o Google alterará a implementação (e eles podem) coisas ruins vão acontecer. Eu realmente espero que goole irá torná-lo disponível para obter o fragmento ao vivo
shem
38

Outra solução simples:

    public class MyPagerAdapter extends FragmentPagerAdapter {
        private Fragment mCurrentFragment;

        public Fragment getCurrentFragment() {
            return mCurrentFragment;
        }
//...    
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (getCurrentFragment() != object) {
                mCurrentFragment = ((Fragment) object);
            }
            super.setPrimaryItem(container, position, object);
        }
    }
Mindphaser
fonte
1
Isso parece perfeito para minhas necessidades atuais de fragmentos.
Danny117 10/10
Se tudo o que você precisa fazer é obter o Fragmento selecionado no momento, é tudo o que você precisa - o método setPrimaryItem é definido no anexo e também em todas as atualizações no conjunto interno do Fragmento como o item atual.
Graeme
1
Isso soa como uma boa solução, mas como setPrimaryItem()é chamado depois ViewPager.OnPageChangeListener#onPageSelected() eu não posso usá-lo :-(
hardysim
21

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 Fragmentdo meu ViewPager. No seu Activityou Fragmentsegurando o ViewPager, você pode usar esse código para percorrer cada Fragmentum deles.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    Fragment viewPagerFragment = fragmentPagerAdapter.getItem(i);
    if(viewPagerFragment != null) {
        // Do something with your Fragment
        // Check viewPagerFragment.isResumed() if you intend on interacting with any views.
    }
}
  • Se você souber a sua posição Fragmentno ViewPager, você pode simplesmente ligar getItem(knownPosition).

  • Se você não sabe a sua posição Fragmentno ViewPager, você pode fazer com que seus filhos Fragmentsimplementem uma interface com um método como esse getUniqueId()e use isso para diferenciá-los. Ou você pode percorrer tudo Fragmentse verificar o tipo de classe, comoif(viewPagerFragment instanceof FragmentClassYouWant)

!!! EDIT !!!

Eu descobri que getItemsó é chamado por FragmentPagerAdapterquando cada um Fragmentprecisa ser criado na primeira vez , depois disso, parece que o Fragmentssão reciclados usando o FragmentManager. Dessa forma, muitas implementações de FragmentPagerAdaptercriação de novos Fragment s getItem. Usando o meu método acima, isso significa que criaremos novos Fragments cada vez que getItemfor chamado à medida que passarmos por todos os itens no FragmentPagerAdapter. Devido a isso, eu encontrei uma abordagem melhor, usando o FragmentManagerpara obter cada um Fragment(usando a resposta aceita). Esta é uma solução mais completa e está funcionando bem para mim.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    String name = makeFragmentName(mViewPager.getId(), i);
    Fragment viewPagerFragment = getChildFragmentManager().findFragmentByTag(name);
    // OR Fragment viewPagerFragment = getFragmentManager().findFragmentByTag(name);
    if(viewPagerFragment != null) {

        // Do something with your Fragment
        if (viewPagerFragment.isResumed()) {
            // Interact with any views/data that must be alive
        }
        else {
            // Flag something for update later, when this viewPagerFragment
            // returns to onResume
        }
    }
}

E você precisará deste método.

private static String makeFragmentName(int viewId, int position) {
    return "android:switcher:" + viewId + ":" + position;
}
Steven Byle
fonte
1
Você acabou de encontrarFragmentByTag (), mas onde poderíamos definir o TAG com fragmento?
VinceStyling
@vince O ViewPagerpróprio define essas tags. Esta solução é frágil porque depende do conhecimento da convenção de nomenclatura "oculta" do ViewPager. A resposta do Streets of Boston é uma solução muito mais abrangente, que agora uso no meu projeto (em vez dessa abordagem).
Steven Byle
Isso funciona muito bem! Mas removi a condicional "if (viewPagerFragment.isResumed ())" porque preciso atualizar minhas páginas ListFragment que estão fora da tela. Então, quando o usuário voltar para a página ListFragment, tudo será atualizado com os novos dados.
JDJ
10

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.

Veedka
fonte
Esta é a resposta perfeita para obter fragmentos antigos do view pager quando a atividade ou fragmento é recriado.
Smeet
7

Para obter o fragmento Visible atual do ViewPager . Estou usando esta declaração simples e está funcionando bem.

      public Fragment getFragmentFromViewpager()  
      {
         return ((Fragment) (mAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem())));
      }
Zar E Ahmer
fonte
3

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:

@Override
onCreate(){
    //initialise the list of fragments
    fragments = new Vector<Fragment>();

    //fill up the list with out fragments
    fragments.add(Fragment.instantiate(this, MainFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, MenuFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, StoresFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, AboutFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, ContactFragment.class.getName()));


    //Set up the pager
    pager = (ViewPager)findViewById(R.id.pager);
    pager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments));
    pager.setOffscreenPageLimit(4);
}

então isso pode ser chamado:

public Fragment getFragment(ViewPager pager){   
    Fragment theFragment = fragments.get(pager.getCurrentItem());
    return theFragment;
}

então eu poderia jogá-lo em uma instrução if que só seria executada se estivesse no fragmento correto

Fragment tempFragment = getFragment();
if(tempFragment == MyFragmentNo2.class){
    MyFragmentNo2 theFrag = (MyFragmentNo2) tempFragment;
    //then you can do whatever with the fragment
    theFrag.costomFunction();
}

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.

Russell Cargill
fonte
1
melhor resposta para mim
Sonu Kumar
3

Isso é baseado na resposta de Steven acima. Isso retornará a instância real do fragmento que já está anexado à atividade pai.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
    for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {

        Fragment viewPagerFragment = (Fragment) mViewPager.getAdapter().instantiateItem(mViewPager, i);
        if(viewPagerFragment != null && viewPagerFragment.isAdded()) {

            if (viewPagerFragment instanceof FragmentOne){
                FragmentOne oneFragment = (FragmentOne) viewPagerFragment;
                if (oneFragment != null){
                    oneFragment.update(); // your custom method
                }
            } else if (viewPagerFragment instanceof FragmentTwo){
                FragmentTwo twoFragment = (FragmentTwo) viewPagerFragment;

                if (twoFragment != null){
                    twoFragment.update(); // your custom method
                }
            }
        }
    }
OrangeTree
fonte
2

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.

Zsombor Erdődy-Nagy
fonte
1
Obrigado pela sua resposta, eu o recupero com o adpter.getItem (); Eu sou um calouro na programação Android. realmente aprecio muito você. Agora eu posso recuperar o ListFragment e quero adicionar footerView a ele. Enquanto faço isso na minha Activity, o logcat é impresso: "java.lang.IllegalStateException: a exibição do conteúdo ainda não foi criada." com isso.
Qun Qin
1
FragmentActivity tem o método onAttachFragment (), administra este trabalho para o ViewPager com conteúdo de fragmento?
Vasil Valchev
2

FragmentPagerAdapter é a fábrica dos fragmentos. Para encontrar um fragmento com base em sua posição, se ainda estiver na memória, use isto:

public Fragment findFragmentByPosition(int position) {
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
    return getSupportFragmentManager().findFragmentByTag(
            "android:switcher:" + getViewPager().getId() + ":"
                    + fragmentPagerAdapter.getItemId(position));
}

Código de amostra para a API de suporte da v4.

Daniel De León
fonte
Ele está retornando nulo em onresume (). Alguma idéia do porquê e enxada para consertá-lo?
seema
2

Você não precisa chamar getItem()ou algum outro método posteriormente para obter a referência de um Fragmenthost hospedado ViewPager. Se você deseja atualizar alguns dados internos Fragment, use esta abordagem: Atualizar o ViewPager dinamicamente?

A chave é definir novos dados dentro Adapere chamar, notifyDataSetChanged()que por sua vez chamará getItemPosition(), passando uma referência sua Fragmente 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.

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(xyzData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}
M-WaJeEh
fonte
Eu não entendo aqui, você precisa de uma referência de um fragmento para usar getItemPosition (), para que você também não use getItemPosition, hein?
getItemPosition()é um método no seu adaptador. Você não vai ligar diretamente. Você tem uma referência do seu adaptador, para adapter.notifyDataSetChanged()ligar e ligar getItemPosition()para o seu adaptador, passando a referência dos seus Fragments. Você pode ver uma implementação completa em ação aqui stackoverflow.com/questions/19891828/…
M-WaJeEh
Eu li isso e ainda não entendi. Você ainda precisaria de uma referência direta a esses fragmentos para fazer chamadas contra eles, certo? Você menciona isso como um hack, mas não vejo uma alternativa; O adapter.getItem (i) obviamente não está funcionando.
2
Ok, atualizei minha resposta para esclarecer mais. É claro que é necessária uma referência para atualizar um, Fragmentmas como obter uma referência é passível de debate. Outras soluções obter referência de FragmentManagerusar uma corda semelhante a "android:switcher:"+idou retornando POSITION_NONEde getItemosition()causando todos os fragmentos para recriar-se.
M-WaJeEh
Obrigado, isso faz muito mais sentido e corresponde à minha experiência (então, talvez eu não esteja fazendo algo errado, ha).
2

Deve se estender FragmentPagerAdapterà sua classe de adaptador do ViewPager.
Se você usar FragmentStatePagerAdapter, não poderá encontrar o seu Fragmentpelo seuID

public static String makeFragmentName(int viewPagerId, int index) {
  return "android:switcher:" + viewPagerId + ":" + index;
}

Como usar este método: -

Fragment mFragment = ((FragmentActivity) getContext()).getSupportFragmentManager().findFragmentByTag(
       AppMethodUtils.makeFragmentName(mViewPager.getId(), i)
);
InterestViewFragment newFragment = (InterestViewFragment) mFragment;
mahesh_babariya
fonte
2

Ei, eu respondi a esta pergunta aqui . Basicamente, você precisa substituir

public Object instantiateItem (container ViewGroup, int position)

método de FragmentStatePagerAdapter.

Utkarsh Saxena
fonte
1

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.

Nathan
fonte
0

A maneira mais fácil e concisa. Se todos os seus fragmentos ViewPagerforem de classes diferentes, você poderá recuperá-los e diferenciá-los da seguinte maneira:

public class MyActivity extends Activity
{

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        if (fragment.getClass() == MyFragment.class) {
            mMyFragment = (MyFragment) fragment;
        }
    }

}
riwnodennyk
fonte
Isso também está errado, pois existem vários fragmentos que são anexados quando você usa o ViewPager. existe o fragmento de página atual e outro à esquerda e outro à direita. Isso permite que o usuário deslize entre eles sem precisar inicializá-los apenas quando o usuário os alcançar.
desenvolvedor android
0

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.

lxknvlk
fonte
0

Crie um ID de recurso inteiro em /values/integers.xml

<integer name="page1">1</integer>
<integer name="page2">2</integer>
<integer name="page3">3</integer>

Em seguida, na função getItem do PagerAdapter:

public Fragment getItem(int position) {

        Fragment fragment = null;

        if (position == 0) {
            fragment = FragmentOne.newInstance();
            mViewPager.setTag(R.integer.page1,fragment);

        }
        else if (position == 1) {

            fragment = FragmentTwo.newInstance();
            mViewPager.setTag(R.integer.page2,fragment);

        } else if (position == 2) {

            fragment = FragmentThree.newInstance();
            mViewPager.setTag(R.integer.page3,fragment);

        }

        return fragment;
        }

Em atividade, escreva esta função para obter uma referência de fragmento:

private Fragment getFragmentByPosition(int position) {
    Fragment fragment = null;

    switch (position) {
        case 0:
            fragment = (Fragment) mViewPager.getTag(R.integer.page1);
            break;

        case 1:

            fragment = (Fragment) mViewPager.getTag(R.integer.page2);
            break;

        case 2:
            fragment = (Fragment) mViewPager.getTag(R.integer.page3);
            break;
            }

            return fragment;
    }

Obtenha a referência do fragmento chamando a função acima e, em seguida, faça a conversão no seu fragmento personalizado:

Fragment fragment = getFragmentByPosition(position);

        if (fragment != null) {
                    FragmentOne fragmentOne = (FragmentOne) fragment;
                    }
user2574090
fonte
0

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) .

public PlaceholderFragment getFragmentByPosition(Integer pos){
    for(Fragment f:getChildFragmentManager().getFragments()){
        if(f.getId()==R.id.viewpager && f.getArguments().getInt("SECTNUM") - 1 == pos) {
            return (PlaceholderFragment) f;
        }
    }
    return null;
}
Evgeny
fonte
0

Em Fragmento

public int getArgument(){
   return mPage;
{
public void update(){

}

Em FragmentActivity

List<Fragment> fragments = getSupportFragmentManager().getFragments();
for(Fragment f:fragments){
    if((f instanceof PageFragment)&&(!f.isDetached())){
          PageFragment pf = (PageFragment)f;   
          if(pf.getArgument()==pager.getCurrentItem())pf.update();
    }
}
Mark Zhuravlyov
fonte
0

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);

SUMIT MONAPARA
fonte
-1

Ok para o adaptador FragmentStatePagerAdapter , financio uma solução:

em seu FragmentActivity:

ActionBar mActionBar = getSupportActionBar(); 
mActionBar.addTab(mActionBar.newTab().setText("TAB1").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment1.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB2").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment2.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB3").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment3.class.getName())));

viewPager = (STViewPager) super.findViewById(R.id.viewpager);
mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), mActionBar);
viewPager.setAdapter(this.mPagerAdapter);

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:

public Fragment getActiveFragment(int position) {
String name = MyPagerAdapter.makeFragmentName(position);
return getSupportFragmentManager().findFragmentByTag(name);
}

no seu adaptador:

public class MyPagerAdapter extends FragmentStatePagerAdapter {

private final ActionBar actionBar;
private final FragmentManager fragmentManager;

public MyPagerAdapter(FragmentManager fragmentManager, com.actionbarsherlock.app.ActionBarActionBar mActionBar) {super(fragmentManager);
this.actionBar = mActionBar;
this.fragmentManager = fragmentManager;
}

@Override
public Fragment getItem(int position) {
getSupportFragmentManager().beginTransaction().add(mTchatDetailsFragment, makeFragmentName(position)).commit();
return (Fragment)this.actionBar.getTabAt(position);
}

@Override
public int getCount() {
return this.actionBar.getTabCount();
}

@Override
public CharSequence getPageTitle(int position) {
return this.actionBar.getTabAt(position).getText();
}

private static String makeFragmentName(int viewId, int index) {
return "android:fragment:" + index;
}

}
douarbou
fonte
-1
Fragment yourFragment = yourviewpageradapter.getItem(int index);

indexé o lugar do fragmento no adaptador como você adicionou fragment1primeiro, então volte a fragment1passar indexcomo 0 e assim por diante

Vishnu Prasad
fonte