ViewPager con niños de ancho fijo

Necesito diseñar un ViewPager que pueda pasar childs con el ancho fijo (por ejemplo los childs con el ancho 700dp), desafortunadamente la versión actual de ViewPager hará automáticamente todo el ancho de los MATCH_PARENT a MATCH_PARENT , hay alguna manera de agregar esta funcionalidad a ViewPager ?

Mi presentación de ViewPager :

 <?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="wrap_content" android:orientation="vertical" > <android.support.v4.view.ViewPager android:id="@+id/some_id" android:layout_width="match_parent" android:layout_height="300dp" android:overScrollMode="never" /> </LinearLayout> 

ViewPager Childs de ViewPager :

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/banner_main_layout_container" android:layout_width="700dp" android:layout_height="match_parent" android:background="#fff" android:gravity="center" android:orientation="vertical" > <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="some images"/> </LinearLayout> 

Gracias por adelantado…

Es posible escalar las páginas dentro del ViewPager con FragmentPagerAdapter.getPageWidth . Necesitará un FragmentPagerAdapter personalizado. Si devuelve un número entre 0 y 1, las páginas se reducen, el ancho> 1 escala las páginas en consecuencia. Pero esto no es realmente bueno, porque no se puede desplazar la imagen dentro de la página escalada.

Si envuelve el ImageView en un HorizontalScrollView , las cosas son un poco mejores, puede desplazar las imágenes dentro de las páginas, pero el gesto de desplazamiento entre las páginas es atrapado por el HorizontalScrollView si no es muy rápido. Vea este video .

Por lo tanto, la solución es realmente utilizar un HorizontalScrollView personalizado (ver InterceptingHorizontalScrollView ) que no permite interceptar el evento onTouch, pero también lo permite cuando el Usuario se desplaza hasta el final (Ver onOverScrolled ). Vea este video o la imagen de abajo para ver la diferencia.

EDIT No es necesario sobrescribir onInterceptTouchEvent, ya que HorizontalScrollView los intercepta de forma predeterminada (para que la imagen tenga mayor prioridad que la paginación).

Por último, aquí está todo el código:

MainActivity.java

 public class MainActivity extends Activity { private ViewPager mViewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Set up the ViewPager mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setPageMargin(30); mViewPager.setAdapter(new ImagePagerAdapter(getFragmentManager())); } private class ImagePagerAdapter extends FragmentPagerAdapter { public ImagePagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { switch(i) { case 0: return ImageFragment.newInstance(R.drawable.forest1); case 1: return ImageFragment.newInstance(R.drawable.forest2); case 2: return ImageFragment.newInstance(R.drawable.forest3); default: return ImageFragment.newInstance(R.drawable.ic_launcher); } } @Override public int getCount() { return 3; } @Override public float getPageWidth(int position) { // Here it is possible to scale page width return super.getPageWidth(position); } } } 

activity_main.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout> 

ImageFragment.java

 public class ImageFragment extends Fragment { private static final String ARG_PARAM1 = "image_resid"; private int mImageResId; public static ImageFragment newInstance(int image_resid) { ImageFragment fragment = new ImageFragment(); Bundle args = new Bundle(); args.putInt(ARG_PARAM1, image_resid); fragment.setArguments(args); return fragment; } public ImageFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mImageResId = getArguments().getInt(ARG_PARAM1); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_image, container, false); ImageView imageView = (ImageView)v.findViewById(R.id.imageView); imageView.setImageResource(mImageResId); return v; } } 

fragment_image.xml

 <com.gyebro.viewpagertest.InterceptingHorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="600dp" android:layout_height="match_parent" tools:context="com.gyebro.viewpagertest.ImageFragment"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:adjustViewBounds="true" android:id="@+id/imageView" android:src="@drawable/forest1" /> </com.gyebro.viewpagertest.InterceptingHorizontalScrollView> 

InterceptingHorizontalScrollView.java

 public class InterceptingHorizontalScrollView extends HorizontalScrollView { public InterceptingHorizontalScrollView(Context context) { super(context); } public InterceptingHorizontalScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public InterceptingHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /*@Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (getParent() != null) { switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: getParent().requestDisallowInterceptTouchEvent(false); break; } } return super.onInterceptTouchEvent(ev); }*/ @Override protected void onOverScrolled (int scrollX, int scrollY, boolean clampedX, boolean clampedY) { super.onOverScrolled(scrollX,scrollY,clampedX,clampedY); // if clampedX == true, we've reached the end of the HorizontalScrollView so // allow parent to intercept if(clampedX) { Log.d("InterceptingHorizontalScrollView", "Reached the end, allowing interception"); getParent().requestDisallowInterceptTouchEvent(false); } } } 

Lo que realmente quieres aquí es un HorizontalScrollView dentro de un ViewPager . Esto requiere manejo táctil personalizado, por lo que querrá utilizar algo como esta clase: InterceptingHorizontalScrollView

Para que InterceptingHorizontalScrollView funcione en ViewPager , tendrá que sobrescribir onOverScrolled :

 @Override protected void onOverScrolled (int scrollX, int scrollY, boolean clampedX, boolean clampedY) { super.onOverScrolled(scrollX,scrollY,clampedX,clampedY); if(clampedX) { getParent().requestDisallowInterceptTouchEvent(false); } } 

Gracias a Gyebro por este consejo. ^

El ViewPager infantil de ViewPager se vería así:

 <com.tumblr.widget.InterceptingHorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/banner_main_layout_container" android:layout_width="700dp" android:layout_height="match_parent" android:background="#fff" android:gravity="center" android:orientation="vertical" > <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="some images"/> </LinearLayout> </com.tumblr.widget.InterceptingHorizontalScrollView> 

Puede anular el método getWidth de PagerAdapter y si esto no ayuda, mire esto: http://commonsware.com/blog/2012/08/20/multiple-view-viewpager-options.html

y lo más importante probar este ejemplo , funciona muy bien! Simplemente siga todo el ejemplo.

  • Los niños de ViewPager / siempre deben coincidir con el ancho de los padres.
  • Además, suena como una mala idea usar un ImageView 700dp de ancho. ¿Qué aspecto tendría en el modo retrato?

Si no desea que el ViewPager sea más pequeño, es decir, desea que el ImageViews se pase desde el lado absoluto de la pantalla, tiene que hacer que los elementos parezcan más pequeños.

Esa imitación se puede hacer creando 2 LinearLayouts adicionales para actuar como espaciadores. Entonces parecería como si su artículo tiene un ancho específico.

He aquí un ejemplo (con un TextView):

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <LinearLayout android:background="#FFF" android:layout_weight="3" android:layout_width="0dp" android:layout_height="match_parent"/> <TextView android:layout_weight="10" android:background="#333" android:textColor="#FFF" android:textSize="50sp" android:gravity="center" android:text="HELLO" android:layout_width="0dp" android:layout_height="match_parent" /> <LinearLayout android:background="#FFF" android:layout_weight="3" android:layout_width="0dp" android:layout_height="match_parent"/> </LinearLayout> 

Y que se vería así: Vista previa de ViewPager

Establezca el margen de página del paginador de vistas en un valor negativo. Esto obligará a las páginas a empujar en el paginador de vista. Sea advertido, también causará la superposición así que usted verá parte del elemento siguiente / anterior en el paginador de la visión.

ViewPager consulta el adaptador dado para cada ancho de página a través del método getPageWidth . Así puede devolver el ancho deseado. Así es como se implementa para la biblioteca de soporte v13:

 public class AdapterFragment extends FragmentPagerAdapter { // other methods @Override public float getPageWidth(int position) { return 700f; // this is 700px, you can convert from DP or SP using TypedValues } } 

También puede devolver un ancho diferente para diferentes páginas según la posición.

  • NullPointerException al mostrar un ViewPager una segunda vez
  • ViewPager dentro de Fragmento pierde su contenido cuando se vuelve a mostrar el fragmento
  • OnPageSelected nunca se llama para el primer elemento?
  • Cómo deshabilitar el adaptador viewpager al tocar vistas específicas?
  • Barra de Acción de Android Sherlock con Tabs
  • Pasar al siguiente fragmento con un clic de botón
  • Android - combinar viewpager horizontal con viewpager vertical
  • Fragmentos anidados pierden llamadas a onCreateOptionsMenu después de rotación de pantalla
  • Animación de Cube Flip para Fragments en Android
  • Acceso a TextView en ViewPager desde la actividad
  • ViewPager analógico para paginación a horizontales y verticales
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.