ViewPager tiene datos de offset incorrectos después de girar la pantalla cuando la página actual no es la primera

Estructura de la aplicación:

Mi aplicación tiene una FragmentActivity única, y que FragmentActivity alberga un Fragment que alberga un ViewPager . El ViewPager tiene un adaptador que subclases FragmentStatePagerAdapater , y que el adaptador reemplaza getItem() para devolver un nuevo Fragmento basado en la posición; getCount() se establece en devolver siempre 2.

El problema:

La aplicación funciona perfectamente hasta que suceda cualquiera de dos cosas: Se produce una rotación cuando ViewPager muestra el segundo fragmento, o si, en onResume() , se le dice al ViewPager que se desplace a una página que no sea la primera. Por lo que puedo decir, estos escenarios son idénticos. Cuando se produce uno de estos eventos, se ha detenido el desplazamiento y el Fragmento visible es el segundo de los fragmentos que gestiona ViewPager, se llama a la devolución de llamada onPageScrolled(int, float, int) con el argumento 'position' en '0' (Debe ser 1) y el argumento 'positionOffset' establecido en '1' (que está fuera del intervalo [0,1) como se prometió en los documentos). Hice algunas exploraciones en el código de ViewPager y descubrí que la función boolean pageScrolled(int xpos) pasa de ser llamada con valores en el rango de [0,940] (0 en la primera página y luego 940 en la segunda) a ser llamado Con valores en el rango [-940,0] (-940 en el primero, 0 en el segundo). Si ViewPager se restableció a pensar que la segunda página era la primera página, entonces esto realmente tiene sentido (una especie de), aunque no es en absoluto lo que quiero.

Algunos Código:

ViewPagerFragment (aloja el ViewPager). MyViewPager es sólo una copia / pegada de ViewPager de la biblioteca de soporte; Quería imprimir algunos de los datos de sus métodos privados.

 public class ViewPagerFragment extends Fragment implements MyViewPager.OnPageChangeListener{ @InjectView(R.id.view_pager) MyViewPager viewPager; @DebugLog public ViewPagerFragment() { setRetainInstance(true); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_view_pager, container, false); ButterKnife.inject(this,view); Log.d("onCreateView()","ViewPagerFragment = "+this.toString()); return view; } @Override public void onResume() { super.onResume(); setupPager(); } void setupPager(){ if(viewPager != null) { if (viewPager.getAdapter() == null) { viewPager.setAdapter(new MyFragmentAdapter(getChildFragmentManager())); } viewPager.setOnPageChangeListener(this); viewPager.setPageMargin(40); } } @Override @DebugLog public void onDestroyView() { super.onDestroyView(); viewPager.setOnPageChangeListener(null); ButterKnife.reset(this); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if(positionOffset == 1f){ Log.d("onPageScrolled","position offset == 1 and position == "+position+". That's bad!"); } else if(position == 1){ Log.d("onPageScrolled","position offset == "+positionOffset+" and position == 1. That's good!"); } } public static class MyFragmentAdapter extends FragmentStatePagerAdapter{ public MyFragmentAdapter(FragmentManager fm) { super(fm); } @Override @DebugLog public Fragment getItem(int position) { return PageFragment.newInstance(position); } @Override public int getCount() { return 2; } } 

}

Mi pregunta, en caso de que no esté implícita, es "¿Qué he hecho para estropear mi ViewPager, y cómo puedo solucionarlo?" Eliminar la llamada setRetainInstance() obviamente restablecerá las cosas a normal, pero luego pierdo mi 'lugar' en ViewPager. La eliminación de la llamada setRetainInstance() y, a continuación, utilizar Bundle savedInstanceState para conservar la posición ViewPager también no funciona (como se mencionó en la parte superior de mi publicación).

¡Gracias por adelantado!

Parece que hay un error en ViewPager después de la rotación.

Calculo el scrollX (offset) de la página actual, y siempre es 0 cuando se hace una página de desplazamiento.

Sin embargo, viene a 1 o X (alrededor del ancho de página, 938 ~ 9 si el ancho de página es 940) después de rotación.

He tenido algunos problemas en onPageScrolled cuando el dispositivo gira, y he resuelto estos llamando a setAdapter nuevo en callback de rotación como onConfigurationChanged .

Aquí hay algunos bloques de código. Device es mi clase personalizada.

 public void configOnOrientationChange() { if (Device.isPortrait(getContext())) { configOnPortraitOrientation(); } else if (Device.isLandscape(getContext())) { configOnLandscapeOrientation(); } int currentItem = mViewPager.getCurrentItem(); if (mPagerAdapter != null) { mViewPager.setAdapter(mPagerAdapter); mViewPager.setCurrentItem(currentItem); } } 

Espero que esto ayude.

  • Navegación de nuevo a FragmentPagerAdapter -> fragmentos están vacíos
  • Infinite Scrolling Image ViewPager
  • Fragmentos en ViewPager se recrean
  • ¿Cómo evito enfocar el último EditText al navegar desde un Fragment con pestañas?
  • Android ViewPager cambia automáticamente la página
  • ViewPager con niños de ancho fijo
  • Android: clics retardados en ListView
  • La recreación de fragmentos de ViewPager se reanuda pero no se ve
  • Cuando se utiliza ViewPager con Fragmentos, los fragmentos se destruyen al deslizar
  • Cómo deslizar imágenes en ViewFlipper o ViewPager
  • Implementación de ViewPager circular
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.