Android: Vertical ViewPager

¿Hay una manera de hacer un ViewPager que no se desplace horizontalmente, pero verticalmente ?!

Puede utilizar un ViewPager.PageTransformer para dar la ilusión de un ViewPager vertical. Para lograr el desplazamiento con un arrastre vertical en lugar de horizontal, tendrá que sobrescribir los eventos táctiles por defecto de MotionEvent y cambiar las coordenadas de MotionEvent antes de manipularlos, por ejemplo:

 /** * Uses a combination of a PageTransformer and swapping X & Y coordinates * of touch events to create the illusion of a vertically scrolling ViewPager. * * Requires API 11+ * */ public class VerticalViewPager extends ViewPager { public VerticalViewPager(Context context) { super(context); init(); } public VerticalViewPager(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { // The majority of the magic happens here setPageTransformer(true, new VerticalPageTransformer()); // The easiest way to get rid of the overscroll drawing that happens on the left and right setOverScrollMode(OVER_SCROLL_NEVER); } private class VerticalPageTransformer implements ViewPager.PageTransformer { @Override public void transformPage(View view, float position) { if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0); } else if (position <= 1) { // [-1,1] view.setAlpha(1); // Counteract the default slide transition view.setTranslationX(view.getWidth() * -position); //set Y position to swipe in from top float yPosition = position * view.getHeight(); view.setTranslationY(yPosition); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); } } } /** * Swaps the X and Y coordinates of your touch event. */ private MotionEvent swapXY(MotionEvent ev) { float width = getWidth(); float height = getHeight(); float newX = (ev.getY() / height) * width; float newY = (ev.getX() / width) * height; ev.setLocation(newX, newY); return ev; } @Override public boolean onInterceptTouchEvent(MotionEvent ev){ boolean intercepted = super.onInterceptTouchEvent(swapXY(ev)); swapXY(ev); // return touch coordinates to original reference frame for any child views return intercepted; } @Override public boolean onTouchEvent(MotionEvent ev) { return super.onTouchEvent(swapXY(ev)); } } 

Por supuesto, puedes ajustar estos ajustes como mejor te parezca. Termina pareciendo esto:

Demostración de VerticalViewPager

Tengo una solución que funciona para mí en dos pasos.

  1. onInstantiateItem() de PagerAdapter , cree la vista y gírela por -90:

     view.setrotation(-90f) 

    Si está utilizando FragmentPagerAdapter , entonces:

     objFragment.getView().setRoration(-90) 
  2. Rotación de la vista ViewPager en 90 grados:

     objViewPager.setRotation(90) 

Funciona como un encanto al menos para mi requisito.

Implementación de pager de vista vertical por Antoine Merle:

https://github.com/castorflex/VerticalViewPager

Para alguien que está luchando con la forma de hacer vertical ViewPager funciona dentro de la horizontal, sólo tiene que hacer lo siguiente:

Vertical ViewPager

 public class VerticalViewPager extends ViewPager { public VerticalViewPager(Context context) { super(context); init(); } public VerticalViewPager(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { setPageTransformer(true, new VerticalPageTransformer()); setOverScrollMode(OVER_SCROLL_NEVER); } private class VerticalPageTransformer implements ViewPager.PageTransformer { @Override public void transformPage(View view, float position) { if (position < -1) { view.setAlpha(0); } else if (position <= 1) { view.setAlpha(1); view.setTranslationX(view.getWidth() * -position); float yPosition = position * view.getHeight(); view.setTranslationY(yPosition); } else { view.setAlpha(0); } } } private MotionEvent swapXY(MotionEvent ev) { float width = getWidth(); float height = getHeight(); float newX = (ev.getY() / height) * width; float newY = (ev.getX() / width) * height; ev.setLocation(newX, newY); return ev; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { boolean intercepted = super.onInterceptTouchEvent(swapXY(ev)); swapXY(ev); return intercepted; } @Override public boolean onTouchEvent(MotionEvent ev) { return super.onTouchEvent(swapXY(ev)); } } 

Horizontal ViewPager

 public class HorizontalViewPager extends ViewPager { private GestureDetector xScrollDetector; public HorizontalViewPager(Context context) { super(context); } public HorizontalViewPager(Context context, AttributeSet attrs) { super(context, attrs); xScrollDetector = new GestureDetector(getContext(), new XScrollDetector()); } class XScrollDetector extends GestureDetector.SimpleOnGestureListener { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return Math.abs(distanceX) > Math.abs(distanceY); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (xScrollDetector.onTouchEvent(ev)) { super.onInterceptTouchEvent(ev); return true; } return super.onInterceptTouchEvent(ev); } } 

Hay una nueva implementación no oficial de código abierto de un ViewPager vertical:

Anuncio: https://plus.google.com/107777704046743444096/posts/1FTJfrvnY8w

Código: https://github.com/LambergaR/VerticalViewPager/

Una ligera extensión esta respuesta me ayudó a lograr mi requisito (Vertical View Pager para animar similar como en Inshorts – Noticias en 60 palabras )

 public class VerticalViewPager extends ViewPager { public VerticalViewPager(Context context) { super(context); init(); } public VerticalViewPager(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { // The majority of the magic happens here setPageTransformer(true, new VerticalPageTransformer()); // The easiest way to get rid of the overscroll drawing that happens on the left and right setOverScrollMode(OVER_SCROLL_NEVER); } private class VerticalPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.75f; @Override public void transformPage(View view, float position) { if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0); } else if (position <= 0) { // [-1,0] // Use the default slide transition when moving to the left page view.setAlpha(1); // Counteract the default slide transition view.setTranslationX(view.getWidth() * -position); //set Y position to swipe in from top float yPosition = position * view.getHeight(); view.setTranslationY(yPosition); view.setScaleX(1); view.setScaleY(1); } else if (position <= 1) { // [0,1] view.setAlpha(1); // Counteract the default slide transition view.setTranslationX(view.getWidth() * -position); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); } } } /** * Swaps the X and Y coordinates of your touch event. */ private MotionEvent swapXY(MotionEvent ev) { float width = getWidth(); float height = getHeight(); float newX = (ev.getY() / height) * width; float newY = (ev.getX() / width) * height; ev.setLocation(newX, newY); return ev; } @Override public boolean onInterceptTouchEvent(MotionEvent ev){ boolean intercepted = super.onInterceptTouchEvent(swapXY(ev)); swapXY(ev); // return touch coordinates to original reference frame for any child views return intercepted; } @Override public boolean onTouchEvent(MotionEvent ev) { return super.onTouchEvent(swapXY(ev)); } } 

Espero que esto pueda ser útil para alguien más.

Compruebe esto: https://github.com/JakeWharton/Android-DirectionalViewPager

O la siguiente pregunta puede ayudarle: Vertical 'Gridview con páginas' o 'Viewpager'

Sólo una mejora en las respuestas de @Brett y @ Salman666 para transformar correctamente coordenadas (X, Y) en (Y, X) ya que las pantallas del dispositivo son rectangulares:

 /** * Swaps the X and Y coordinates of your touch event */ @Override public boolean onTouchEvent(MotionEvent ev) { return super.onTouchEvent(swapXY(ev)); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return super.onInterceptTouchEvent(swapXY(ev)); } private MotionEvent swapXY(MotionEvent ev) { //Get display dimensions float displayWidth=this.getWidth(); float displayHeight=this.getHeight(); //Get current touch position float posX=ev.getX(); float posY=ev.getY(); //Transform (X,Y) into (Y,X) taking display dimensions into account float newPosX=(posY/displayHeight)*displayWidth; float newPosY=(1-posX/displayWidth)*displayHeight; //swap the x and y coords of the touch event ev.setLocation(newPosX, newPosY); return ev; } 

Sin embargo, todavía se necesita hacer algo para mejorar la respuesta de la pantalla táctil. El problema podría estar relacionado con lo que @msdark comentó sobre la respuesta de @ Salman666.

Hay algunos proyectos de código abierto que pretenden hacer esto. Aquí están:

  • Kaelaela / VerticalViewPager , último compromiso en octubre de 2015 y un colaborador
  • Castorflex / VerticalViewPager , la última comisión en febrero de 2014 y tres colaboradores
  • LambergaR / VerticalViewPager / , el último compromiso en agosto de 2013 y un colaborador

Estos han sido marcados desaprobados por sus autores:

Y una cosa más:

  • También hay un nombre de archivo VerticalViewPager.java en la fuente de Android de la aplicación deskclock , pero no parece estar oficialmente admitido, ya que no puedo encontrar documentación para ello.
 import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; public class VerticalViewPager extends ViewPager { public VerticalViewPager(Context context) { super(context); init(); } public VerticalViewPager(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { setPageTransformer(true, new VerticalPageTransformer()); setOverScrollMode(OVER_SCROLL_NEVER); } private class VerticalPageTransformer implements PageTransformer { @Override public void transformPage(View view, float position) { int pageWidth = view.getWidth(); int pageHeight = view.getHeight(); if (position < -1) { view.setAlpha(0); } else if (position <= 1) { view.setAlpha(1); view.setTranslationX(pageWidth * -position); float yPosition = position * pageHeight; view.setTranslationY(yPosition); } else { view.setAlpha(0); } } } @Override public boolean onTouchEvent(MotionEvent ev) { ev.setLocation(ev.getY(), ev.getX()); return super.onTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { ev.setLocation(ev.getY(), ev.getX()); return super.onInterceptTouchEvent(ev); } } 

Ya hay uno en la fuente de Android . Lo he modificado para funcionar mejor sin embargo:

 package com.crnlgcs.sdk.widgets; import android.content.Context; import android.support.v4.view.ViewConfigurationCompat; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewParent; public class VerticalViewPager extends ViewPager { private static final String TAG = "VerticalViewPager"; private static final boolean DEBUG = true; private float mLastMotionX; private float mLastMotionY; private float mTouchSlop; private boolean mVerticalDrag; private boolean mHorizontalDrag; // Vertical transit page transformer private final ViewPager.PageTransformer mPageTransformer = new ViewPager.PageTransformer() { @Override public void transformPage(View view, float position) { final int pageWidth = view.getWidth(); final int pageHeight = view.getHeight(); if (position < -1) { // This page is way off-screen to the left. view.setAlpha(0); } else if (position <= 1) { view.setAlpha(1); // Counteract the default slide transition view.setTranslationX(pageWidth * -position); // set Y position to swipe in from top float yPosition = position * pageHeight; view.setTranslationY(yPosition); } else { // This page is way off-screen to the right. view.setAlpha(0); } } }; public VerticalViewPager(Context context) { super(context, null); } public VerticalViewPager(Context context, AttributeSet attrs) { super(context, attrs); final ViewConfiguration configuration = ViewConfiguration.get(context); mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); init(); } private void init() { // Make page transit vertical setPageTransformer(true, mPageTransformer); // Get rid of the overscroll drawing that happens on the left and right (the ripple) setOverScrollMode(View.OVER_SCROLL_NEVER); } @Override public boolean onTouchEvent(MotionEvent ev) { final float x = ev.getX(); final float y = ev.getY(); if (DEBUG) Log.v(TAG, "onTouchEvent " + x + ", " + y); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: { mLastMotionX = x; mLastMotionY = y; if (!super.onTouchEvent(ev)) return false; return verticalDrag(ev); } case MotionEvent.ACTION_MOVE: { final float xDiff = Math.abs(x - mLastMotionX); final float yDiff = Math.abs(y - mLastMotionY); if (!mHorizontalDrag && !mVerticalDrag) { if (xDiff > mTouchSlop && xDiff > yDiff) { // Swiping left and right mHorizontalDrag = true; } else if (yDiff > mTouchSlop && yDiff > xDiff) { //Swiping up and down mVerticalDrag = true; } } if (mHorizontalDrag) { return super.onTouchEvent(ev); } else if (mVerticalDrag) { return verticalDrag(ev); } } case MotionEvent.ACTION_UP: { if (mHorizontalDrag) { mHorizontalDrag = false; return super.onTouchEvent(ev); } if (mVerticalDrag) { mVerticalDrag = false; return verticalDrag(ev); } } } // Set both flags to false in case user lifted finger in the parent view pager mHorizontalDrag = false; mVerticalDrag = false; return false; } private boolean verticalDrag(MotionEvent ev) { final float x = ev.getX(); final float y = ev.getY(); ev.setLocation(y, x); return super.onTouchEvent(ev); } } 

Un repositorio actualmente más activo es lsjwzh / RecyclerViewPager .

  • Last commit 12 Ago 2016, 16 Colaboradores, 1840 estrellas
  • Basado en RecyclerView
  • Circular ViewPager que utiliza FragmentPagerAdapter
  • Android cuando ViewPager inserta como Child get error android.view.ViewGroup.jumpDrawablesToCurrentState (ViewGroup.java:5035)
  • Android ViewPager Con animación diferente como acercar, atenuarse, etc
  • Android, Cómo mezclar ActionBar.Tab + Ver Pager + ListFragment
  • Uso de android.app.Fragment con ViewPager en Android 3.0+
  • Android - combinar viewpager horizontal con viewpager vertical
  • Ocultar Soft Keyboard en la aplicación para Android Desde fragmentos de ViewPager
  • Cómo agregar una vista personalizada en ViewPager para un tutorial
  • Deshabilitar los gestos en PagerAdapter / ViewPager
  • Utilizar FragmentStatePagerAdapter sin biblioteca de soporte
  • Cómo reemplazar fragmento a otro fragmento en TabLayout y ViewPager
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.