Implementación de un TabListener utilizando la biblioteca de soporte

Estoy intentando implementar la navegación por pestañas, pero quiero asegurarme de que las personas que tengan versiones anteriores de Android todavía puedan usar mi aplicación.

La aplicación en mente ATM es bastante simple, sólo quiero ser capaz de entender cómo implementar el diseño y luego voy a añadir los bits que faltan.

De todos modos, tengo una actividad de contenedor que extiende la actividad de fragmentos (para asegurar la compatibilidad), y esta actividad crea un TabView con una ActionBar (creo que mi problema reside aquí). La aplicación intentará crear tres pestañas y agregarlas a ActionBar, y quiero asegurarme de que el usuario pueda desplazarse hacia delante y hacia atrás usando la navegación lateral.

Aquí está TabListener que estoy intentando implementar:

public static class TabListener<T extends Fragment> implements ActionBar.TabListener { private Fragment mFragment; private final Activity mActivity; private final String mTag; private final Class<T> mClass; public TabListener(Activity activity, String tag, Class<T> clz) { mActivity = activity; mTag = tag; mClass = clz; } public void onTabSelected(Tab tab, FragmentTransaction ft) { if (mFragment == null) { mFragment = Fragment.instantiate(mActivity, mClass.getName()); ft.add(android.R.id.content, mFragment, mTag); } else { ft.attach(mFragment); } } public void onTabUnselected(Tab tab, FragmentTransaction ft) { if (mFragment != null) { ft.detach(mFragment); } } public void onTabReselected(Tab tab, FragmentTransaction ft) { } } 

Aquí están mis importaciones, porque quería asegurarse de que estaba usando la biblioteca de soporte:

 import android.app.ActionBar; import android.app.ActionBar.Tab; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.ViewPager; import android.view.Menu; 

Sin embargo, Eclipse me está dando problemas con los métodos TabListener . Me dice lo siguiente: "El tipo LayoutContainer.TabListener debe implementar el método abstracto heredado ActionBar.TabListener.onTabSelected (ActionBar.Tab, FragmentTransaction)"

Cuando selecciono Añadir métodos no implementados Eclipse básicamente añade los métodos OnTabSelected OnTabReselected y OnTabUnselected , pero esta vez, pasando la versión no compatible del Fragmento ( android..app.Fragment ) como parámetro.

¿Alguna idea sobre cómo hacer otra implementación de la navegación lateral a través de la biblioteca de soporte para asegurar la compatibilidad?

 actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); actionBar.setDisplayShowHomeEnabled(false); actionBar.setDisplayShowTitleEnabled(false); tabA = actionBar.newTab().setText(""); tabB = actionBar.newTab().setText(""); Fragment fragmentA = new AFragmentTab(); Fragment fragmentB = new BFragmentTab(); tabA.setTabListener(new MyTabsListener(fragmentA)); tabB.setTabListener(new MyTabsListener(fragmentB)); actionBar.addTab(tabA); actionBar.addTab(tabB); 

El listener de la pestaña es como sigue:

 protected class MyTabsListener implements ActionBar.TabListener{ private Fragment fragment; public MyTabsListener(Fragment fragment){ this.fragment = fragment; } public void onTabSelected(Tab tab, FragmentTransaction ft){ ft.add(R.id.layout2, fragment, null); } public void onTabReselected(Tab tab, FragmentTransaction ft) { } public void onTabUnselected(Tab tab, FragmentTransaction ft) { ft.remove(fragment); } } 

Y luego hacer una clase para cada ficha:

 public class BFragmentTab extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.login, container, false); } } 

Pero tenga en cuenta que la barra de acción no es compatible con las versiones de Android inferiores a 3.0. Si desea utilizarlo en versiones anteriores le sugiero que use la biblioteca de actionBarSherlock.

Hmmm Mientras que las obras de Malek no responden directamente a la pregunta ..

Simplemente puede ignorar la transacción de fragmentos que recibe en la devolución de llamada y utilizar su propia:

 android.support.v4.app.FragmentTransaction fft = mActivity.getSupportFragmentManager().beginTransaction(); 

Sólo asegúrese de que su actividad es una FragmentActivity y podrá iniciar una nueva transacción de fragmentos.

También el método replace () en el fragmentTransaction es mucho más conveniente que add () y remove ()

La clave es usar

 import android.support.v7.app.ActionBar; 

… más bien que …

 import android.app.ActionBar; 

Eso evita la ingeniosa solución Nelson Ramírez.

El siguiente ejemplo completo, basado en la documentación oficial , se probó para funcionar desde Android 3.0, API 11

 package com.example.myapp; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import android.view.*; import android.widget.TextView; public class NavigationTabsBasicDemoActivity extends ActionBarActivity { static public class TabListener<T extends Fragment> implements ActionBar .TabListener { private Fragment mFragment; private final Activity mActivity; private final String mTag; private final Class<T> mClass; /** * Constructor used each time a new tab is created. * * @param activity The host Activity, used to instantiate the * fragment * @param tag The identifier tag for the fragment * @param pClass The fragment's Class, used to instantiate the * fragment * @see <a * href="http://developer.android.com/guide/topics/ui/actionbar * .html#Tabs"> * Developers Guide > Action Bar > Adding Navigation Tabs</a> */ public TabListener(Activity activity, String tag, Class<T> pClass) { mActivity = activity; mTag = tag; mClass = pClass; } @Override public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) { if (mFragment == null) { mFragment = Fragment.instantiate(mActivity, mClass.getName()); ft.add(android.R.id.content, mFragment, mTag); } else { // If it exists, attach it in order to show it ft.attach(mFragment); } } @Override public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) { if (mFragment != null) { // Detach the fragment, because another one is about to be // attached. ft.detach(mFragment); } } @Override public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) { // Do nothing. } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // No need for setContentView() to be used, Instead we use the root // android.R.id.content as the container for each fragment, // which is set in the TabListener ActionBar actionBar = getSupportActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); actionBar.setDisplayShowTitleEnabled(true); ActionBar.Tab tab = actionBar.newTab().setText("Artist").setTabListener( new TabListener<PlaceholderFragment>(this, "artist", PlaceholderFragment .class)); actionBar.addTab(tab); tab = actionBar.newTab().setText("Album").setTabListener( new TabListener<PlaceholderFragment>( this, "album", PlaceholderFragment.class)); actionBar.addTab(tab); } /** * In this example use one Fragment but display different data based on * which * tab is shown. In production you'd probably use a separate fragment. */ public static class PlaceholderFragment extends Fragment { public PlaceholderFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate( R.layout.fragment_navigation_tabs_basic_demo, container, false); TextView outputTextView = (TextView) rootView.findViewById( R.id.output_textView); outputTextView.setText("Hello " + getTag()); return rootView; } } } 

Quería implementar @ nelson-ramirez pero tenía un error al acceder a mActivity, así que esta es una combinación de esas dos respuestas, y funciona para mi proyecto, que utiliza una pestaña de navegación con inicio de sesión en Facebook (que requiere la biblioteca support.v4). Las claves son, la creación de una mActivity privado que luego pasar y asignar al iniciar el oyente, y la creación de su propia Fragmento de transacción, no utilizando el del argumento. Además, cambie la actividad principal a FragmentActivity, utilizando la biblioteca v4, que permite el acceso a getSupportFragmentManager ().

 public class MyTabListener implements ActionBar.TabListener{ private Fragment fragment; private FragmentActivity mActivity; public MyTabListener(Fragment fragment, FragmentActivity activity){ this.fragment = fragment; this.mActivity = activity; } @Override public void onTabSelected(ActionBar.Tab tab, android.app.FragmentTransaction ft) { android.support.v4.app.FragmentTransaction fft = mActivity.getSupportFragmentManager().beginTransaction(); fft.replace(R.id.fragment_container, fragment); fft.commit(); } @Override public void onTabUnselected(ActionBar.Tab tab, android.app.FragmentTransaction ft) { android.support.v4.app.FragmentTransaction fft = mActivity.getSupportFragmentManager().beginTransaction(); fft.remove(fragment); } @Override public void onTabReselected(ActionBar.Tab tab, android.app.FragmentTransaction ft) { } } 

¿Alguna idea sobre cómo hacer otra implementación de la navegación lateral a través de la biblioteca de soporte para asegurar la compatibilidad?

Solución alternativa

A partir del 29 de mayo de 2015, puede utilizar la Biblioteca de soporte de diseño de Android . Incluye un Tab Layout y soporta dispositivos Android 2.1 o superiores.

  • Eliminar salto de línea en TabLayout
  • Android DialogFragment onViewCreated no se llama
  • Problema de superposición de sugerencias de TextInputLayout
  • Cómo elegir PreferenceFragmentCompat
  • Iconos de flecha de retroceso y desbordamiento de color incorrecto en dispositivos pre-Lollipop después de actualizar a la biblioteca de soporte 23.2.0
  • ¿Cómo puedo utilizar las bibliotecas de soporte de android v4 y v13 en el mismo proyecto?
  • El método getSupportFragmentManager () no está definido
  • Fragmento getView () devuelve null en una devolución de llamada OnClickListener
  • ¿La biblioteca de soporte de v4 usa nuevas clases cuando está disponible?
  • Error después de actualizar la AppCompat de Android.Support Library v7 a la versión 21.0.3
  • La aplicación se bloquea en rotación sin stackTrace
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.