2011-12-21 11 views

Respuesta

46

Finalmente encontré an answer que trabajó para mí. Básicamente, puede acceder al fragmento de una página de viewPager usando la etiqueta "android: switcher:" + R.id.viewpager + ": 0".

+27

El método en la respuesta vinculada no funciona con FragmentStatePagerAdapter, pero la [segunda respuesta] (http://stackoverflow.com/a/8886019/237820) a la misma pregunta vinculada tiene un método que sí lo hace. –

+4

Si bien esto podría responder teóricamente a la pregunta, [sería preferible] (http://meta.stackoverflow.com/q/8259) incluir aquí las partes esenciales de la respuesta y proporcionar el enlace de referencia. – Keelan

1

Se ha explicado aquí: http://developer.android.com/guide/topics/fundamentals/fragments.html

En OnCreateView debe devolver el fin de trazar una interfaz de usuario para su fragmento, creo que es la relación.

También esta pregunta podría ser similar: Get focused View from ViewPager

+0

Hola Dante, sí, entiendo eso, pero estoy tratando de obtener el Fragmento, dada la Vista. – MitchellSalad

+0

Ok, ¿qué pasa con 'getFragmentManager(). FindFragmentById (R.id.fragment_container);' then? Obtendrás el fragmento actual en ese contenedor, creo. – Dante

+1

Encontré esta página porque tengo el mismo problema. findFragmentById no funciona para mí. – James

1

Puede hacerlo: - En la medida de clase de un adaptador de vista localizador (como PagerAdapter, FragmentStatePagerAdapter ...) método de reemplazo instantiateItem:

@Override 
public Object instantiateItem(ViewGroup container, int position) { 
     final Fragment frag = (Fragment) super.instantiateItem(container, position); 
     if(frag instanceof ListNoteOfTypeFragment){     
      final ListNoteOfTypeFragment listNoteOfTypeFragment = (ListNoteOfTypeFragment) frag; 
      //do whatever you want with your fragment here 
      listNoteOfTypeFragment.setNoteChangeListener(mListener); 
     } 
     return frag; 
    }  
5

Editar - No haga esto. Si está tentado, lea los comentarios de por qué es una mala idea.

Por impar oportunidad que todavía estamos tratando de resolver este problema:

Extender FragmentPagerAdapter. En el constructor, construya los Fragmentos que necesita y almacénelos en una Lista (array/ArrayList) de Fragmentos.

private final int numItems = 3; 
Fragment[] frags; 

public SwipeAdapter (FragmentManager fm) { 
    super(fm); 

    //Instantiate the Fragments 
    frags = new Fragment[numItems]; 

    Bundle args = new Bundle(); 
    args.putString("arg1", "foo"); 

    frags[0] = new MyFragment(); 
    frags[1] = new YourFragment(); 
    frags[2] = new OurFragment(); 
    frags[2].setArguments(args); 
} 

Luego de getItem(int position), se puede hacer algo como

public Fragment getItem(int position) { 
    return frags[position]; 
} 

No estoy seguro si esta es la forma generalmente aceptada de hacerlo pero funcionó para mí.

Editar

Esto no es realmente una buena manera de ir. Si planeas manejar los cambios de orientación o si tu aplicación está en segundo plano, es probable que esto rompa tu código. Por favor, lea los comentarios debajo de esta respuesta para más información. Más bien use la respuesta de @James

+0

su solución está bien si la pre-creación de cada fragmento no es una objeción. Sin embargo, no subestimes lo costoso que pueden ser tus fragmentos. – Rene

+1

Buen punto. También he tenido problemas con esta manera cuando las actividades se reinician, y los fragmentos ''getActivity()' no devuelve la actividad actual, pero alguna instancia anterior que ha sido destruida –

+2

Esto funciona hasta que gires el dispositivo. Entonces los fragmentos sobrevivirán a la rotación, pero la memoria caché de su adaptador no lo hará. Ahora, cuando solicite el fragmento mostrado actualmente, creará un nuevo fragmento que no se utilizará en absoluto. –

18

He resuelto este problema al revés. En lugar de buscar el fragmento de la actividad, estoy registrando el Fragmento durante su método onAttach() en su actividad de propietario y anulándolo en el método onStop(). Idea básica:

Fragmento:

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    try{ 
     mActivity = (IMyActivity)activity; 
    }catch(ClassCastException e){ 
     throw new ClassCastException(activity.toString() +" must be a IMyActivity"); 
    } 

    mActivity.addFragment(this); 
} 

@Override 
public void onStop() { 
    mActivity.removeFragment(this); 
    super.onStop(); 
} 

IMyActivity:

public interface IFriendActivity { 
    public void addFragment(Fragment f); 
    public void removeFragment(Fragment f); 
} 

MyActivity:

public class MyActivity implements IMyActivity{ 

    [...] 

    @Override 
    public void addFragment(Fragment f) { 
     mFragments.add(f); 
    } 

    @Override 
    public void removeFragment(Fragment f) { 
     mFragments.remove(f); 
    } 

} 
+1

Una vez que haya registrado sus fragmentos, ¿cómo lo encuentra según su posición? –

3

POR FAVOR NO use este

Haga su adaptador de extender la FragmentStatePagerWithCurrentAdapter clase siguiente y en lugar de implementar getItem implementar el mismo código en getItemAtIndex

Ajuste el ViewPagerOnPageChangeListener, a la instancia del adaptador.

Cuando necesite acceder al Fragmento actual simplemente llame al adapter.getCurrentItem().

package your.package; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentStatePagerAdapter; 
import android.support.v4.view.ViewPager.OnPageChangeListener; 
import android.util.SparseArray; 
import android.view.ViewGroup; 

public abstract class FragmentStatePagerWithCurrentAdapter 
extends FragmentStatePagerAdapter 
implements OnPageChangeListener { 
    int currentPage = 0; 

    private SparseArray<Fragment> mPageReferenceMap = new SparseArray<Fragment>(); 

    public FragmentStatePagerWithCurrentAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public final Fragment getItem(int index) { 
     Fragment myFragment = getItemAtIndex(index); 
     mPageReferenceMap.put(index, myFragment); 
     return myFragment; 
    } 

    public abstract Fragment getItemAtIndex(int index); 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 

     super.destroyItem(container, position, object); 

     mPageReferenceMap.remove(Integer.valueOf(position)); 
    } 

    public Fragment getCurrentItem() { 
     return mPageReferenceMap.get(currentPage); 
    } 

    @Override 
    public void onPageScrollStateChanged(int arg0) { 

    } 

    @Override 
    public void onPageScrolled(int arg0, float arg1, int arg2) { 

    } 

    @Override 
    public void onPageSelected(int newPageIndex) { 
     currentPage = newPageIndex; 
    } 

} 

que utiliza como referencia la siguiente entrada en el blog: http://tamsler.blogspot.com/2011/11/android-viewpager-and-fragments-part-ii.html

+2

Esto no es correcto. En caso de rotación del dispositivo, el sistema recreará el fragmento llamando al constructor del fragmento sin pasar por PagerAdapter.getItem. La única alternativa viable es guardar el objeto fragmento en Fragment.onAttach como muestra sdl. –

+0

@StephenCheng Tienes razón. Cuando usé esto, tenía una aplicación de retrato fija, pero luego descubrí el problema que mencionas cuando la actividad se canceló debido a la presión de la memoria y luego se recargó el estado. Terminé reescribiendo este código en uno mucho más complejo para manejar todos los escenarios que necesitábamos, incluido este. –

0

Jorge Garcia's FragmentStatePagerWithCurrentAdapter es una muy buena solución, pero necesita una mejora menor. En caso de que la actividad se destruya y vuelva a crearse en respuesta a un cambio de configuración o algo así, no se solicitará el getItem para los fragmentos que fueron guardados y recuperados por el administrador de fragmentos. Así que puedo reemplazar getItem normalmente en mi subclase y puse lo siguiente en el FragmentStatePagerWithCurrentAdapter

@Override 
public Object instantiateItem(ViewGroup container, int position) { 
    Object item = super.instantiateItem(container, position); 
    if (item instanceof Fragment) { 
     pageReferenceMap.put(position, (Fragment)item); 
    } 
    return item; 
} 

El instantiateItem se llama cada vez que se accede al fragmento en esa posición.

-2

Creo que hay es la mejor manera mediante el uso de esta

Log.i(TAG, "getCurrentItem " + mViewPager.getCurrentItem());

se puede obtener de la página actual fragmento de pantalla.

1

respuesta definitiva que funciona sin problemas (pero pequeño pico):

en algún lugar de la disposición del fragmento de la página:

<FrameLayout android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone" android:id="@+id/fragment_reference"> 
    <View android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone"/> 
</FrameLayout> 

en onCreateView del fragmento():

... 
View root = inflater.inflate(R.layout.fragment_page, container, false); 
ViewGroup ref = (ViewGroup)root.findViewById(R.id.fragment_reference); 
ref.setTag(this); 
ref.getChildAt(0).setTag("fragment:" + pageIndex); 
return root; 

y el método para volver Fragmento de ViewPager, si existe:

public Fragment getFragment(int pageIndex) {   
     View w = mViewPager.findViewWithTag("fragment:" + pageIndex); 
     if (w == null) return null; 
     View r = (View) w.getParent(); 
     return (Fragment) r.getTag(); 
} 
0

O simplemente guardar todos los fragmentos en un mapa:

public class MyFragment extends Fragment implements OnPageChangeListener { 

    private ViewPager viewPager; 
    private FragmentStatePagerAdapter viewAdapter; 
    private View rootView; 
    private Map<Integer, Fragment> fragments = new HashMap<Integer, Fragment>(); 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

     rootView = inflater.inflate(R.layout.introdution, container, false); 

     viewPager = (ViewPager) rootView.findViewById(R.id.pager); 
     viewAdapter = new ViewAdapter(getFragmentManager()); 
     viewPager.setAdapter(viewAdapter); 
     viewPager.addOnPageChangeListener(this); 

     return rootView; 

    } 

    private class ViewAdapter extends FragmentStatePagerAdapter { 

     public ViewAdapter(FragmentManager fragmentManager) { 
      super(fragmentManager); 
     } 

     @Override 
     public Fragment getItem(int position) { 

      Fragment result = null; 

      switch (position) { 
       case 0: result = Fragment1.newInstance(); break; 
       case 1: result = Fragment2.newInstance(); break; 
      } 

      if (result != null) 
       fragments.put(position, result); 

      return result; 

     } 

     @Override 
     public int getCount() { 

      return 2; 
     } 

    } 

    @Override 
    public void onPageScrollStateChanged(int arg0) { 
    } 

    @Override 
    public void onPageScrolled(int arg0, float arg1, int arg2) { 
    } 

    @Override 
    public void onPageSelected(int position) { 

     Fragment currentFragment = fragments.get(position); 

    } 

} 
5

Sí, es posible si se está utilizando FragmentStatePagerAdapter.

ViewPager vp; 
//... 
YourFragment fragment = (YourFragment) adapter.instantiateItem(vp, vp.getCurrentItem()); 
Cuestiones relacionadas