Abaixo está o meu código, que foi 3 Fragment classes
incorporado a cada uma das 3 guias ViewPager
. Eu tenho uma opção de menu. Como mostrado na onOptionsItemSelected()
, selecionando uma opção, preciso atualizar o fragmento que está visível no momento. Para atualizar que eu tenho que chamar um método que está na classe de fragmento. Alguém pode sugerir como chamar esse método?
public class MainActivity extends ActionBarActivity {
ViewPager ViewPager;
TabsAdapter TabsAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewPager = new ViewPager(this);
ViewPager.setId(R.id.pager);
setContentView(ViewPager);
final ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//Attaching the Tabs to the fragment classes and setting the tab title.
TabsAdapter = new TabsAdapter(this, ViewPager);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass1"),
FragmentClass1.class, null);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass2"),
FragmentClass2.class, null);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass3"),
FragmentClass3.class, null);
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.addText:
**// Here I need to call the method which exists in the currently visible Fragment class**
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());
}
public static class TabsAdapter extends FragmentPagerAdapter
implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(ActionBarActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int position) {
// TODO Auto-generated method stub
mActionBar.setSelectedNavigationItem(position);
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
tabPosition = tab.getPosition();
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
@Override
public int getCount() {
return mTabs.size();
}
}
}
Suponha que abaixo está a classe de fragmento com o método que updateList()
eu quero chamar:
public class FragmentClass1{
ArrayList<String> originalData;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.frag1, container, false);
originalData = getOriginalDataFromDB();
return fragmentView;
}
public void updateList(String text)
{
originalData.add(text);
//Here I could do other UI part that need to added
}
}
Respostas:
Uma maneira simples de fazer isso é usar um truque relacionado à
FragmentPagerAdapter
implementação:Por favor, repensar sua convenção de nomenclatura de variáveis, usando como nome da variável o nome da classe é muito confuso (portanto
ViewPager ViewPager
, não , useViewPager mPager
por exemplo).fonte
instantiateItem()
método e a obtenção de referências aos fragmentos adequados.mAdapter.getItem(position)
, incrível ... Pelo menos agora eu sei que os outros 8512 ensaios não funcionaram. Obrigadofonte
onPageSelected
/onPageDeselected
e todos os meus fragmentos de pager o estendem. Em seguida, vocêsetPrimaryitem
pode chamar esses métodos adequadamente quando o usuário passar para uma nova página. Isso significa que você pode implementar uma estratégia mais lenta para carregar dados em páginas que nem são mostradas. No entanto, você deve ter em mente que, durante a transição da página, parecerá melhor se a próxima página já estiver preenchida com dados; portanto, o carregamento lento de todos os dadosonPageSelected
poderá não ser o ideal.if
declaração? O fragmento apenas chama oequals
método do objeto, que é uma comparação superficial. Então, por que nem sempre ligarmCurrentFragment = ((Fragment) object);
?Antes de tudo, acompanhe 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", é necessário 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:
Espero que ajude!
fonte
Essa é a única maneira de não obter NullPointerException para as variáveis de instância dessas classes de fragmento em particular. Isso pode ser útil para outras pessoas que ficaram com a mesma coisa. No onOptionsItemSelected (), codifiquei da maneira abaixo:
fonte
FragmentStatePagerAdapter
sem substituir nenhum código. De fato, deve ser tão simples quanto uma função apenas retornarviewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem())
.FragmentStatePagerAdapter possui um método público com o nome instantiateItem que retorna seu fragmento com base nos valores de parâmetros especificados, esse método possui dois parâmetros ViewGroup (ViewPager) e position.
Usou esse método para obter o fragmento da posição especificada,
fonte
Sei que é tarde demais, mas tenho maneiras muito simples de fazê-lo,
// para fragmento na posição 0
fonte
Há muitas respostas aqui que realmente não abordam o fato básico de que não há NENHUMA MANEIRA de fazer isso de forma previsível, e de uma maneira que não resulte em um tiro no pé em algum momento no futuro.
FragmentStatePagerAdapter
é a única classe que sabe como acessar de maneira confiável os fragmentos rastreados peloFragmentManager
- qualquer tentativa de tentar adivinhar o ID ou a tag do fragmento não é confiável a longo prazo. E as tentativas de rastrear as instâncias manualmente provavelmente não funcionarão bem quando o estado for salvo / restaurado, poisFragmentStatePagerAdapter
pode não chamar os retornos de chamada quando o estado for restaurado.A única coisa que pude fazer funcionar é copiar o código
FragmentStatePagerAdapter
e adicionar um método que retorna o fragmento, dada uma posição (mFragments.get(pos)
). Observe que esse método pressupõe que o fragmento esteja realmente disponível (ou seja, estava visível em algum momento).Se você é particularmente aventureiro, pode usar a reflexão para acessar os elementos da
mFragments
lista particular , mas voltamos à estaca zero (o nome da lista não garante a mesma).fonte
Transmitir a instância recuperada da linha acima para o fragmento em que você deseja trabalhar. Funciona perfeitamente bem.
é a instância do pager que gerencia os fragmentos.
fonte
Para obter uma referência ao fragmento visível no momento, suponha que você tenha uma referência a
ViewPager
comomPager
. Em seguida, as etapas a seguir obterão uma referência paracurrentFragment
:PageAdapter adapter = mPager.getAdapter();
int fragmentIndex = mPager.getCurrentItem();
FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
Fragment currentFragment = fspa.getItem(fragmentIndex);
A única linha usada do elenco 3 é válida normalmente.
FragmentStatePagerAdapter
é um adaptador útil para um ViewPager.fonte
A melhor maneira de fazer isso é chamar o fragmento CallingFragmentName = (CallingFragmentName) viewPager .getAdapter () .instantiateItem (viewPager, viewPager.getCurrentItem ()); Ele instanciará novamente seu fragmento de chamada, para que não atinja uma exceção de ponteiro nulo e chame qualquer método desse fragmento.
fonte
Fragmento atual:
Isso funciona se você criou um projeto com o modelo da barra de tabulação de fragmentos.
Observe que isso funciona com a implementação padrão do modelo de atividade com guias.
fonte
Eu usei o seguinte:
fonte
FragmentStatePagerAdapter
tem uma variável de instância privada chamadamCurrentPrimaryItem
do tipoFragment
. Só podemos nos perguntar por que os desenvolvedores do Android não forneceram um getter. Essa variável é instanciada nosetPrimaryItem()
método Portanto, substitua esse método para que você obtenha a referência a essa variável. Acabei declarando minha própriamCurrentPrimaryItem
e copiando o conteúdo desetPrimaryItem()
para a minha substituição.Na sua implementação de
FragmentStatePagerAdapter
:fonte
Você pode definir o
PagerAdapter
como este, em seguida, você será capaz de obter qualquerFragment
noViewPager
.Para obter a corrente
Fragment
fonte
Quando usamos o viewPager, uma boa maneira de acessar a instância do fragmento em atividade é instantiateItem (viewpager, index). // index-index do fragmento do qual você deseja instância.
por exemplo, estou acessando a instância de fragmento de 1 index-
fonte
Eu tive o mesmo problema e o resolvi usando esse código.
Apenas substitua o nome MyFragment pelo nome do seu fragmento e adicione o ID do seu contêiner de fragmento.
fonte
Isso é mais à prova do futuro do que a resposta aceita:
fonte
O cenário em questão é melhor atendido por cada fragmento, adicionando seus próprios itens de menu e manipulando diretamente onOptionsItemSelected (), conforme descrito na documentação oficial . É melhor evitar truques não documentados.
fonte
ViewPager
problema?Depois de ler todos os comentários e respostas, vou explicar uma solução ideal para esse problema. A melhor opção é a solução da @ rik, então minha melhoria é baseada na dele.
Em vez de precisar perguntar a cada FragmentClass como
Crie sua própria interface e faça com que seus fragmentos filhos a implementem, algo como
Então, você pode fazer algo assim para iniciar e atualizar seus fragmentos internos.
PS Cuidado ao colocar esse código, se você chamar insatiateItem antes que o sistema realmente o crie, o
savedInstanceState
fragmento de seu filho será nulo.Irá travar seu aplicativo.
Boa sorte
fonte
Com base no que ele respondeu @chahat jain:
"Quando usamos o viewPager, uma boa maneira de acessar a instância do fragmento em atividade é instantiateItem (viewpager, index). // index-index do fragmento do qual você deseja instância."
Se você quer fazer isso no kotlin
0 0 para a instância de fragmento de 0
// ================================================== ========================= // // ##################### ######## Exemplo de usos ################################## // // == ==================================================== ===================== //
Aqui está um exemplo completo para obter uma visão perdida sobre
aqui está o meu veiewPager no arquivo .xml
E a atividade em casa onde insiro a guia
fonte
Na minha implementação anterior, eu armazenei uma lista de fragmentos filhos para poder acessá-los mais tarde, mas isso acabou sendo uma implementação errada, causando enormes vazamentos de memória.
Acabo usando o
instantiateItem(...)
método para obter o fragmento atual:Ou para obter qualquer outro fragmento na posição:
Da documentação :
fonte
Na minha atividade eu tenho:
fonte
Às vezes, o fragmento pode despachar um objeto nulo, para que você possa executar um novo Runnable para resolver o problema no primeiro carregamento.
Obrigado Rick
fonte
Substitua setPrimaryItem do FragmentPagerAdapter: o objeto é o fragmento visível:
fonte
Simplesmente obtenha o item atual do pager e peça ao seu adaptador o fragmento dessa posição.
fonte
getItem
criar uma nova instância?Para obter o fragmento atual - obtenha a posição no ViewPager em public void onPageSelected (final int position) e, em seguida,
SECTNUM - argumento de posição atribuído em estático público PlaceholderFragment newInstance (int sectionNumber);de fragmento
getChildFragmentManager () ou getFragmentManager () - depende de como foi criado o SectionsPagerAdapter
fonte
Você pode implementar um BroadcastReceiver no fragmento e enviar uma intenção de qualquer lugar. O receptor do fragmento pode ouvir a ação específica e invocar o método da instância.
Uma ressalva é garantir que o componente View já esteja instanciado e (e para algumas operações, como rolar uma lista, o ListView já deve ser renderizado).
fonte
Este é o hack mais simples:
(código kotlin)
Basta ligar
instantiateItem(viewPager, viewPager.getCurrentItem()
e lançar paraFragment
. Seu item já seria instanciado. Para ter certeza de que você pode adicionar uma verificaçãogetCount
.Funciona com ambos
FragmentPagerAdapter
eFragmentStatePagerAdapter
!fonte
Se o seu pager estiver dentro de um fragmento, use o seguinte:
Onde
R.id.myViewPagerId
está o ID do seu ViewPager dentro do Layout xml.fonte
Você pode declarar uma matriz de fragmento como registrar fragmentos
Então você pode usá-lo como
fonte