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í.

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.

  • ¿Cómo configurar la alarma cuando el móvil ha estado inactivo usando android?
  • Enviar arrays con Intent.putExtra
  • Comenzando a programar en lenguajes dinámicos en Android ((J) Ruby, Clojure ...)
  • Serialización y subclases
  • ¿Cuál es la mejor manera de acercarse? Utilizar PJSIP o SIP Android API para crear una aplicación de llamada basada en SIP
  • Cómo calibrar el sensor de orientación en android?
  • ¿Cómo leer el formato Json.NET ISO 8601 en Gson?
  • Cómo matar un hilo en Android?
  • Intenta invocar método de interfaz en una referencia de objeto nulo finishComposingText ()
  • Android: Redireccionar a otra actividad después del retardo
  • Parse Json en el estudio android de String
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.