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.

  • Cambiar la duración de la animación ViewPager al deslizar de forma programática
  • Android: desplazamiento ViewPager basado en la velocidad
  • Insertar páginas en el medio de un FragmentPageAdapter
  • La recreación de fragmentos de ViewPager se reanuda pero no se ve
  • Utilizar Pull to Refresh gridview en viewpager en Activity within ActivityGroup provoca ClassCastException
  • Android ViewPager, cómo hacer que las vistas de los hermanos sean más pequeñas y más oscuras
  • No recorte las páginas de ViewPager
  • FragmentPagerAdapter no se puede resolver con un tipo
  • Cómo destruir fragmentos antiguos en FragmentStatePagerAdapter
  • ViewPager con la API de Google Maps v2: vista negra misteriosa
  • Hacer ViewPager rápido con la resistencia más corta
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.