A continuación se muestra mi código que tiene 3 Fragment classes
cada uno incrustado con cada una de las 3 pestañas ViewPager
. Tengo una opción de menú. Como se muestra en onOptionsItemSelected()
, al seleccionar una opción, necesito actualizar el fragmento que está visible actualmente. Para actualizar eso, tengo que llamar a un método que está en la clase de fragmento. ¿Alguien puede sugerir cómo llamar a ese 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();
}
}
}
Supongamos que a continuación se muestra la clase de fragmento con el método al updateList()
que quiero llamar:
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
}
}
Respuestas:
Una manera simple de hacer esto es usar un truco relacionado con la
FragmentPagerAdapter
implementación:Reconsidere su convención de nomenclatura variable, usando como nombre de la variable el nombre de la clase es muy confuso (así que no
ViewPager ViewPager
, useViewPager mPager
por ejemplo).fuente
instantiateItem()
método y obteniendo referencias a los fragmentos adecuados usted mismo.mAdapter.getItem(position)
, increíble ... Al menos ahora sé que los otros 8512 ensayos no funcionaron. Graciasfuente
onPageSelected
/onPageDeselected
y hago que todos mis fragmentos de buscapersonas lo extiendan. LuegosetPrimaryitem
puede llamar a estos métodos de manera apropiada cuando el usuario pase a una nueva página. Esto significa que puede implementar una estrategia más perezosa para cargar datos en páginas que ni siquiera se muestran. Sin embargo, debe tener en cuenta que durante la transición de la página se ve mejor si la página siguiente ya está llena de datos, por lo que la carga diferida de todos los datosonPageSelected
puede no ser ideal.if
declaración? Fragment solo llama alequals
método del objeto, que es una comparación superficial. Entonces, ¿por qué no simplemente siempre llamarmCurrentFragment = ((Fragment) object);
?En primer lugar, realice un seguimiento de todas las páginas de fragmentos "activos". En este caso, realiza un seguimiento de las páginas de fragmentos en el FragmentStatePagerAdapter, que es utilizado por ViewPager.
Para evitar mantener una referencia a las páginas de fragmentos "inactivos", debe implementar el método destroyItem (...) de FragmentStatePagerAdapter:
y cuando necesite acceder a la página actualmente visible, llame a:
Donde el método getFragment (int) de MyAdapter se ve así:
Espero que pueda ayudar!
fuente
Esta es la única forma en que no obtengo NullPointerException para las variables de instancia de esas clases de fragmentos en particular. Esto podría ser útil para otros que se atascaron en lo mismo. En onOptionsItemSelected (), codifiqué la siguiente manera:
fuente
FragmentStatePagerAdapter
sin anular ningún código. De hecho, debería ser tan simple como una función solo regresarviewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem())
.FragmentStatePagerAdapter tiene un método público con el nombre instantiateItem que devuelve su fragmento en función de los valores de parámetros especificados, este método tiene dos parámetros ViewGroup (ViewPager) y posición.
Usó este método para obtener el fragmento de la posición especificada,
fuente
Sé que es demasiado tarde, pero tengo formas muy simples de hacerlo,
// para fragmento en posición 0
fuente
Aquí hay muchas respuestas que realmente no abordan el hecho básico de que realmente NO HAY MANERA de hacer esto de manera predecible, y de una manera que no resulte en que te dispares en el pie en algún momento en el futuro.
FragmentStatePagerAdapter
es la única clase que sabe cómo acceder de manera confiable a los fragmentos que son rastreados porFragmentManager
- cualquier intento de tratar de adivinar la identificación o etiqueta del fragmento no es confiable a largo plazo. Y los intentos de rastrear las instancias manualmente probablemente no funcionarán bien cuando se guarde / restaure el estado, ya que esFragmentStatePagerAdapter
posible que no se invoquen las devoluciones de llamada cuando se restaura el estado.Casi lo único que he podido hacer es copiar el código
FragmentStatePagerAdapter
y agregar un método que devuelve el fragmento, dada una posición (mFragments.get(pos)
). Tenga en cuenta que este método supone que el fragmento está realmente disponible (es decir, era visible en algún momento).Si eres particularmente aventurero, puedes usar la reflexión para acceder a los elementos de la
mFragments
lista privada , pero luego volvemos al punto de partida (no se garantiza que el nombre de la lista permanezca igual).fuente
Transmita la instancia recuperada de la línea anterior al fragmento con el que desea trabajar. Funciona perfectamente bien.
es la instancia del localizador que gestiona los fragmentos.
fuente
Para obtener una referencia al fragmento visible actualmente, suponga que tiene una referencia a
ViewPager
asmPager
. Luego, los siguientes pasos obtendrán una referencia acurrentFragment
:PageAdapter adapter = mPager.getAdapter();
int fragmentIndex = mPager.getCurrentItem();
FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
Fragment currentFragment = fspa.getItem(fragmentIndex);
El único elenco utilizado en la línea 3 suele ser válido.
FragmentStatePagerAdapter
es un adaptador útil para un ViewPager.fuente
La mejor manera de hacerlo es simplemente llamar a CallingFragmentName fragment = (CallingFragmentName) viewPager .getAdapter () .instantiateItem (viewPager, viewPager.getCurrentItem ()); Volverá a crear una instancia de su Fragmento de llamada, de modo que no arrojará una excepción de puntero nulo y llamará a cualquier método de ese fragmento.
fuente
Fragmento actual:
Esto funciona si creó un proyecto con la plantilla de la barra de pestañas Fragmentos.
Tenga en cuenta que esto funciona con la implementación de plantilla de actividad con pestañas predeterminada.
fuente
He usado lo siguiente:
fuente
FragmentStatePagerAdapter
tiene una variable de instancia privada llamadamCurrentPrimaryItem
de tipoFragment
. Uno solo puede preguntarse por qué los desarrolladores de Android no le proporcionaron un getter. Esta variable se instancia en elsetPrimaryItem()
método. Por lo tanto, anule este método de tal manera que obtenga la referencia a esta variable. Simplemente terminé declarando el míomCurrentPrimaryItem
y copiando el contenido desetPrimaryItem()
mi anulación.En su implementación de
FragmentStatePagerAdapter
:fuente
Se puede definir el
PagerAdapter
como esto, entonces usted será capaz de obtener ningunaFragment
enViewPager
.Para obtener la corriente
Fragment
fuente
Cuando usamos viewPager, una buena forma de acceder a la instancia de fragmento en actividad es instantiateItem (viewpager, index). // index- index of fragment del cual quieres instancia.
por ejemplo, estoy accediendo a la instancia de fragmento de 1 index-
fuente
En mi implementación anterior, almacené una lista de Fragmentos secundarios para poder acceder a ellos más tarde, pero resultó ser una implementación incorrecta que causó grandes pérdidas de memoria.
Termino usando el
instantiateItem(...)
método para obtener el Fragmento actual:O para obtener cualquier otro Fragmento en posición:
De la documentación :
fuente
Tuve el mismo problema y lo resolví usando este código.
Simplemente reemplace el nombre MyFragment con el nombre de su fragmento y agregue la identificación de su contenedor de fragmentos.
fuente
Esto es más a prueba de futuro que la respuesta aceptada:
fuente
El escenario en cuestión es mejor atendido por cada Fragmento agregando sus propios elementos de menú y manejando directamente onOptionsItemSelected (), como se describe en la documentación oficial . Es mejor evitar los trucos indocumentados.
fuente
ViewPager
problema agregar un elemento de menú ?Después de leer todos los comentarios y respuestas, voy a explicar una solución óptima para este problema. La mejor opción es la solución de @ rik, por lo que mi mejora se basa en la suya.
En lugar de tener que preguntar a cada FragmentClass como
Cree su propia interfaz y haga que los fragmentos de su hijo la implementen, algo así como
Luego, puede hacer algo como esto para iniciar y actualizar sus fragmentos internos.
PD Tenga cuidado donde coloca ese código, si llama a insatiateItem antes de que el sistema realmente lo cree, el
savedInstanceState
fragmento de su hijo será nulo para elloBloqueará tu aplicación.
Buena suerte
fuente
Basado en lo que respondió @chahat jain:
"Cuando usamos viewPager, una buena forma de acceder a la instancia de fragmento en actividad es instantiateItem (viewpager, index). // index- index of fragment of cuya instancia desea".
Si quieres hacer eso en Kotlin
0 a la instancia de fragmento de 0
// ================================================ ========================= // // ##################### ######## Ejemplo de usos ################################# // // == ================================================== ===================== //
Aquí hay un ejemplo completo para obtener una visión más perdida sobre
aquí está mi veiewPager en el archivo .xml
Y la actividad de casa donde inserto la pestaña
fuente
En mi actividad tengo:
fuente
A veces, el fragmento puede enviar un objeto nulo, por lo que puede ejecutar un nuevo Runnable para resolver el problema en la primera carga.
Gracias rick
fuente
Anule setPrimaryItem de su FragmentPagerAdapter: el objeto es el fragmento visible:
fuente
Simplemente obtenga el elemento actual del buscapersonas y luego solicite a su adaptador el fragmento de esa posición.
fuente
getItem
crea una nueva instanciaPara obtener el fragmento actual: obtenga una posición en ViewPager en public void onPageSelected (posición int final) , y luego
SECTNUM: argumento de posición asignado en el marcador de posición estático público newInstance (int sectionNumber); de fragmento
getChildFragmentManager () o getFragmentManager () - depende de cómo se creó SectionsPagerAdapter
fuente
Puede implementar un BroadcastReceiver en el Fragmento y enviar una intención desde cualquier lugar. El receptor del fragmento puede escuchar la acción específica e invocar el método de la instancia.
Una advertencia es asegurarse de que el componente Ver ya esté instanciado y (y para algunas operaciones, como desplazar una lista, ListView ya debe estar renderizado).
fuente
Este es el truco más simple:
(código kotlin)
Solo llame
instantiateItem(viewPager, viewPager.getCurrentItem()
y envíeloFragment
. Su artículo ya estaría instanciado. Para asegurarse de que puede agregar un cheque paragetCount
.Funciona con ambos
FragmentPagerAdapter
yFragmentStatePagerAdapter
!fuente
Si su buscapersonas está dentro de un Fragmento, use esto:
¿Dónde
R.id.myViewPagerId
está la identificación de su ViewPager dentro del diseño xml?fuente
Puede declarar una matriz de fragmentos como fragmentos de registro
Entonces puedes usarlo como
fuente