without with viewpager tablayout studio fragments example android android-fragments android-viewpager

android - viewpager - tablayout without fragments



Fragmento en ViewPager no restaurado después de popBackStack (2)

Problema

Un Fragmento no se vuelve a conectar a su ViewPager de alojamiento después de regresar de otro fragmento.

Situación

Una actividad que aloja un fragmento cuyo diseño contiene un ViewPager ( PageListFragment en el ejemplo a continuación). El ViewPager está poblado por un FragmentStateViewPagerAdapter. Los Fragmentos individuales alojados dentro del localizador ( PageFragment en el ejemplo a continuación) pueden abrir listas de subpáginas, que contienen un nuevo conjunto de páginas.

Comportamiento

Todo funciona bien siempre que no se presione el botón Atrás. Tan pronto como el usuario cierra una de las Listas de Páginas secundarias, se recrea la Lista anterior, pero sin la Página que se mostró previamente. Pasar por las otras páginas en la PageList principal aún funciona.

Código

Una aplicación de ejemplo se puede encontrar en github :

Activity

public class MainActivity extends FragmentActivity { private static final String CURRENT_FRAGMENT = MainActivity.class.getCanonicalName() + ".CURRENT_FRAGMENT"; public static final String ARG_PARENTS = "Parents"; public void goInto(String mHostingLevel, String mPosition) { Fragment hostingFragment = newHostingFragment(mHostingLevel, mPosition); addFragment(hostingFragment); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); addBaseFragment(); } private void addBaseFragment() { Fragment hostingFragment = newHostingFragment("", ""); addFragment(hostingFragment); } private Fragment newHostingFragment(String mHostingLevel, String oldPosition) { Fragment hostingFragment = new PageListFragment(); Bundle args = new Bundle(); args.putString(ARG_PARENTS, mHostingLevel + oldPosition +" > "); hostingFragment.setArguments(args); return hostingFragment; } private void addFragment(Fragment hostingFragment) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragmentSpace, hostingFragment, CURRENT_FRAGMENT); transaction.addToBackStack(null); transaction.commit(); } }

PageListFragment

public class PageListFragment extends Fragment { private String mParentString; public PageListFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_hosting, container, false); } @Override public void onResume() { mParentString = getArguments().getString(MainActivity.ARG_PARENTS); ViewPager viewPager = (ViewPager) getView().findViewById(R.id.viewPager); viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getFragmentManager(),mParentString)); super.onResume(); } private static class SimpleFragmentStatePagerAdapter extends FragmentStatePagerAdapter { private String mHostingLevel; public SimpleFragmentStatePagerAdapter(FragmentManager fm, String hostingLevel) { super(fm); this.mHostingLevel = hostingLevel; } @Override public android.support.v4.app.Fragment getItem(int position) { PageFragment pageFragment = new PageFragment(); Bundle args = new Bundle(); args.putString(MainActivity.ARG_PARENTS, mHostingLevel); args.putInt(PageFragment.ARG_POSITION, position); pageFragment.setArguments(args); return pageFragment; } @Override public int getCount() { return 5; } } }

PageFragment

public class PageFragment extends Fragment { public static final String ARG_POSITION = "Position"; private String mHostingLevel; private int mPosition; public PageFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View contentView = inflater.inflate(R.layout.fragment_page, container, false); setupTextView(contentView); setupButton(contentView); return contentView; } private void setupTextView(View contentView) { mPosition = getArguments().getInt(ARG_POSITION); mHostingLevel = getArguments().getString(MainActivity.ARG_PARENTS); TextView text = (TextView) contentView.findViewById(R.id.textView); text.setText("Parent Fragments " + mHostingLevel + " /n/nCurrent Fragment "+ mPosition); } private void setupButton(View contentView) { Button button = (Button) contentView.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { openNewLevel(); } }); } protected void openNewLevel() { MainActivity activity = (MainActivity) getActivity(); activity.goInto(mHostingLevel, Integer.toString(mPosition)); } }


Después de una larga investigación, resulta ser un problema con el administrador de fragmentos.

Cuando se usa un constructo como el que está arriba de la transacción del fragmento para volver a unir el fragmento a la lista de páginas, se descarta silenciosamente. Básicamente es el mismo problema que causa un

java.lang.IllegalStateException: Recursive entry to executePendingTransactions

cuando intentas alterar los fragmentos dentro de FragmentPager.

La misma solución, en cuanto a los problemas con este error, también es aplicable aquí. Al construir el FragmentStatePagerAdapter, proporcione el administrador de fragmentos hijo correcto.

En lugar de

viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getFragmentManager(),mParentString));

hacer

viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getChildFragmentManager(),mParentString));

Ver también: github


Lo que Paul no ha mencionado es que si usa getChildFragmentManager , sufrirá el problema de "pantalla en blanco al presionar la parte posterior".