Navegación anterior separada para un buscador de vistas con pestañas en Android

Lo que quiero.

En un contexto de menú deslizante de pestaña, quiero reemplazar un fragmento por otro dentro de una pestaña y mantener el menú de pestañas y también la pestaña actual. Cuando se desliza a otra pestaña y vuelve a la original, quiero que se muestre el último fragmento.

Por ejemplo, tengo tab_a con Fragment_1 , tab_b con Fragment_4 y tab_c con Fragment_7 . Ahora quiero un botón en Fragment_1 que me abre Fragment_2 , pero quiero poder deslizar a los fragmentos de la tab_b y tab_c . Y cuando vuelva a tab_a, Fragment_2 debe ser mostrado.

Introduzca aquí la descripción de la imagen

 MainActivity | | ContainerFragment | | |_ _ _ Tab A | |_ _ _ Fragment 1 | | | |_ _ _ Fragment 2 | | | |_ _ _ Fragment 3 | | | |_ _ _ ... | |_ _ _ Tab B | |_ _ _ Fragment 4 | | | |_ _ _ Fragment 5 | | | |_ _ _ Fragment 6 | | | |_ _ _ ... | |_ _ _ Tab C | |_ _ _ Fragment 7 | | | |_ _ _ Fragment 8 | | | |_ _ _ Fragment 8 | | | |_ _ _ ... 

Mi actividad principal actual.

Xml

 <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="fixed" app:tabGravity="fill"/> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </android.support.design.widget.CoordinatorLayout> 

Código

 public class MainActivity extends AppCompatActivity { private TabLayout tabLayout; private final static int[] tabIcons = { R.drawable.ic_tab_a, R.drawable.ic_tab_b, R.drawable.ic_tab_c }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager); setupViewPager(viewPager); tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.setupWithViewPager(viewPager); setupTabIcons(); } private void setupTabIcons() { tabLayout.getTabAt(0).setIcon(tabIcons[0]); tabLayout.getTabAt(1).setIcon(tabIcons[1]); tabLayout.getTabAt(2).setIcon(tabIcons[2]); } private void setupViewPager(ViewPager viewPager) { ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); adapter.addFrag(new Fragment1()); adapter.addFrag(new Fragment4()); adapter.addFrag(new Fragment7()); viewPager.setAdapter(adapter); } class ViewPagerAdapter extends FragmentPagerAdapter { private final List<Fragment> mFragmentList = new ArrayList<>(); ViewPagerAdapter(FragmentManager manager) { super(manager); } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } @Override public int getCount() { return mFragmentList.size(); } void addFrag(Fragment fragment) { mFragmentList.add(fragment); } } } 

Fragmentos

Xml

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:background="@android:color/holo_blue_light" android:id="@+id/fragment_1" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="myContext"> <Button android:text="Go to next Fragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_centerHorizontal="true" android:id="@+id/button_nextFrag" /> <FrameLayout android:id="@+id/tab1_container" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout> 

Código

 public class Fragment1 extends Fragment { private void goNextFragment() { FragmentTransaction trans = getFragmentManager().beginTransaction(); trans.replace(R.id.tab1_container, new Fragment2()); trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); trans.addToBackStack(null); trans.commit(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment. View root = inflater.inflate(R.layout.fragment_1, container, false); // Go to next Fragment Button. final Button nextFrag = (Button) root.findViewById(R.id.button_nextFrag); nextFrag .setOnClickListener(new View.OnClickListener() { public void onClick(View v) { goNextFragment(); } }); return root; } } 

Editar:

Tengo algunas soluciones, pero ninguna es perfecta. Si pongo un Framelayaout en MainActivity, Fragment_1 se reemplaza correctamente a Fragment_2 , pero también está en tab_b y tab_c . Si FrameLayout está en Fragment_1 , puedo deslizar las otras pestañas correctamente, pero el reemplazo no es bueno, porque Fragment_2 está abierto, pero Fragment_1 también está allí.

3 Solutions collect form web for “Navegación anterior separada para un buscador de vistas con pestañas en Android”

Puede usar un ViewPager junto con un TabLayout .

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> <android.support.design.widget.TabLayout android:id="@+id/tablayout" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> 

A continuación, cree una clase que extienda FragmentStatePagerAdapter para inicializar ViewPager con su Fragment inicial s:

 public class CustomPagerAdapter extends FragmentStatePagerAdapter { private final List<String> tabTitles = new ArrayList<String>() {{ add("Fragment 1"); add("Fragment 4"); add("Fragment 7"); }}; private List<Fragment> tabs = new ArrayList<>(); public CustomPagerAdapter(FragmentManager fragmentManager) { super(fragmentManager); initializeTabs(); } private void initializeTabs() { tabs.add(HostFragment.newInstance(new Fragment1())); tabs.add(HostFragment.newInstance(new Fragment4())); tabs.add(HostFragment.newInstance(new Fragment7())); } @Override public Fragment getItem(int position) { return tabs.get(position); } @Override public int getCount() { return tabs.size(); } @Override public CharSequence getPageTitle(int position) { return tabTitles.get(position); } } 

Los fragmentos que contienen el contenido real deben ser envueltos por un HostFragment , que utiliza su FragmentManager hijo para reemplazar el fragmento actual por uno nuevo si desea navegar, o para hacer estallar el último fragmento de la pila de fragmentos. Llame a su replaceFragment para navegar:

 public class HostFragment extends BackStackFragment { private Fragment fragment; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.host_fragment, container, false); if (fragment != null) { replaceFragment(fragment, false); } return view; } public void replaceFragment(Fragment fragment, boolean addToBackstack) { if (addToBackstack) { getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).addToBackStack(null).commit(); } else { getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).commit(); } } public static HostFragment newInstance(Fragment fragment) { HostFragment hostFragment = new HostFragment(); hostFragment.fragment = fragment; return hostFragment; } } 

El HostFragment debe extender la clase abstracta BackstackFragment

 public abstract class BackStackFragment extends Fragment { public static boolean handleBackPressed(FragmentManager fm) { if(fm.getFragments() != null){ for(Fragment frag : fm.getFragments()){ if(frag != null && frag.isVisible() && frag instanceof BackStackFragment){ if(((BackStackFragment)frag).onBackPressed()){ return true; } } } } return false; } protected boolean onBackPressed() { FragmentManager fm = getChildFragmentManager(); if(handleBackPressed(fm)){ return true; } else if(getUserVisibleHint() && fm.getBackStackEntryCount() > 0){ fm.popBackStack(); return true; } return false; } } 

Alambre todo en la MainActivity :

 public class MainActivity extends AppCompatActivity { private CustomPagerAdapter customPagerAdapter; private ViewPager viewPager; private TabLayout tabLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewpager); tabLayout = (TabLayout) findViewById(R.id.tablayout); customPagerAdapter = new CustomPagerAdapter(getSupportFragmentManager()); // 2 is enough for us; increase if you have more tabs! viewPager.setOffscreenPageLimit(2); viewPager.setAdapter(customPagerAdapter); tabLayout.setupWithViewPager(viewPager); } @Override public void onBackPressed() { if(!BackStackFragment.handleBackPressed(getSupportFragmentManager())){ super.onBackPressed(); } } public void openNextFragment() { HostFragment hostFragment = (HostFragment) customPagerAdapter.getItem(viewPager.getCurrentItem()); // your logic to change the fragments... } } 

Esta solución no es ciertamente perfecta pero consigue el trabajo hecho. Leer más fluff sobre ello en mi blog en el tema.

Basado en lo que usted explicó Implemente lo siguiente:

1- En su actividad, cree sus Tabs y ViewPager :

  mPager = (ViewPager) findViewById(R.id.vp_pager); mPager.setOffscreenPageLimit(3); PagerAdapter mAdapter = new PagerAdapter(getSupportFragmentManager(), getContext()); mPager.setAdapter(mAdapter); //tab.setupWithViewPager(mPager); 

2- En cada ViewPager crear ViewPager (Supongo que quieres pestañas dentro de las tabs si no necesitas que las pestañas las eliminen). La implementación de cada fragment sería algo como:

  ViewPager mPager = (ViewPager) rootView.findViewById(R.id.vp_pager); mPager.setOffscreenPageLimit(3); CategoryAdapter mAdapter = new CategoryAdapter(getChildFragmentManager());//make sure this ChildFragmentManager mPager.setAdapter(mAdapter); 

También en fragmento crear un botón que cuando haga clic va a otro fragmento:

  button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mPager.setCurrentItem(1); // go to second fragment } }); 

El resultado final sería algo como seguir y cuando Si vas a las pestañas de inicio y luego vuelve a la pestaña de categoría que su posición de Fragment no se ha cambiado.

Dos puntos que debe recordar:

  1. Set mPager.setOffscreenPageLimit(3); Si no quieres destruir tu fragmento
  2. En fragmento interno pase getChildFragmentManager() lugar de FragmentManager()

Introduzca aquí la descripción de la imagen

Si no necesitas ViewPager Inner Y solo quieres cargar una instancia de Fragment a tiempo aquí es otra opción:

1- Haga el primer artículo de la manera anterior.

2- En tu fragmento xml ponemos FrameContainer y cargamos tu fragmento dentro de él:

  CategoryResultFragment f = CategoryResultFragment.newInstance(); getFragmentManager().beginTransaction() .replace(R.id.frame_result_container, f) .commit(); 

Editar: Este no es el mejor enfoque, pero creo que resolver su problema:

1- Crear un campo estático en su MainActivity como sigue:

 static String[] type = new String[3]; 

2- Cuando llame a onClick en su fragmento, actualice String valor String en MainActivity .

 public static update currentType(int pos,String type); 

El primer valor es la posición ViewPager, el segundo valor es el tipo de fragmento interno (por ejemplo: fragment_d);

3- En su ViewPager

  @Override public Fragment getItem(int position) { switch (position) { case 0: // first tab if(type[position] == "fragment_d") return new Fragment_D(); else return new Fragment_B(); } } 

Puede cambiar fragmentos dentro del fragmento de página. Por ejemplo, TAB_A implementa la lógica de escoger el fragmento 1 o 2, y mostrar el fragmento escogido dentro. La jerarquía se ve así:

ViewPager -> TAB_A -> fragmento 1 o 2 (que se muestra dentro de TAB_A).

También debe utilizar getChildFragmentManager () para administrar fragmentos dentro de TAB_A.

  • El proveedor de ubicación fusionado no obtiene ubicación a menos que GPS esté activado
  • Cargando parcialmente las imágenes de la URL, como lo que se implementa en WhatsApp
  • Cómo eliminar elementos de arraylist genérico en Android (Java)
  • Error de sintaxis en el token "class"
  • Necesita ayuda para cambiar de actividad
  • Otras opciones de la biblioteca de Android TextToSpeech
  • ¿Cómo convertir geopoint longitud + latitud a doble?
  • AsyncTask hilo sigue allí después de ejecutar, ¿es normal?
  • No se puede verificar la llamada de método de simulación desde el suscriptor de RxJava
  • Calcular la distancia real recorrida por el móvil
  • Otras herramientas de desarrollo para Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.