Red de conocimiento informático - Material del sitio web - Cómo realizar el vínculo entre dos ViewPagers

Cómo realizar el vínculo entre dos ViewPagers

ViewPager vinculado significa que cuando un ViewPager se desliza, el otro ViewPager también se deslizará con él y los dos están sincronizados.

Si ViewPager tuviera una interfaz de devolución de llamada sobre la distancia de movimiento, eso no sería un problema. Desafortunadamente, no la hay. Intenté usar onPageScrolled(int

. posición, flotar en el parámetro OnPageChangeListener positionOffset, int positionOffsetPixels), pero falló.

Entonces es solo un ViewPager personalizado.

Simplemente sacaré el código fuente de ViewPager rushing v4 y eliminaré algunas cosas innecesarias hasta que ya no pueda encontrar esta clase.

Además de eliminar ViewPager, también debe eliminar la clase PagerAdapter relacionada; de lo contrario, ViewPager usa la suya propia y el adaptador usa la suya propia y v4, lo que puede causar problemas.

Para implementar el enlace, agregue una variable privada mFollowViewPager en ViewPager (también agregue el método set de la variable):

private ViewPager mFollowViewPager;

public void setFlolwViewPager(página ViewPager){

mFollowViewPager = page;

}

Mi idea es llamar al método scrollTo de mFollowViewPager en el código relacionado con el desplazamiento actual de ViewPager. método.

Entonces, ¿cuál es el mejor lugar para agregarlo? Después de rastrear cuidadosamente el comportamiento de ViewPager, descubrí que cuando no se suelta el dedo, el método formDrag manejará el movimiento relacionado y llamará a su propio método scrollTo para implementar su propia traducción, por lo que solo necesitamos agregar el siguiente código. en el método formDrag: //agregar por jcodecraeer

final float pageOffset = scrollX / ancho;

if(mFollowViewPager!=null){

mFollowViewPager.scrollTo ( (int)( pageOffset*mFollowViewPager.getWidth()), mFollowViewPager.getScrollY());

}

Tenga en cuenta que el ViewPager principal no se mueve la misma distancia que el mFollowViewPager . Dado que los anchos de los dos ViewPagers pueden ser diferentes, es necesario convertirlos. El pageOffset flotante final = scrollX / width;pageOffset

en el código anterior es el valor obtenido después de la conversión.

El performDrag reescrito es el siguiente:

private boolean performDrag(float x) {

boolean needInvalidate = false

final float; deltaX = mLastMotionX - x;

mLastMotionX = x;

flotar oldScrollX = getScrollX()

flotar scrollX = oldScrollX + deltaX; p>final int width = getWidth();

float leftBound = ancho * mFirstOffset;

float rightBound = ancho * mLastOffset;

boolean leftAbsolute = true;

boolean rightAbsolute = true;

Información del elemento final firstItem = mItems.get(0);

Info del elemento final lastItem = mItems.get(mItems.size( ) - 1);

if (firstItem.position ! = 0) {

leftAbsolute = false;

leftBound = firstItem.offset * ancho;

}

if (lastItem.position != mAdapter.getCount() - 1) {

rightAbsolute = false;

rightBound = lastItem. desplazamiento * ancho;

}

if (scrollX < leftBound) {

if (leftAbsolute) {

flotar sobre = leftBound - scrollX;

needsInvalidate = mLeftEdge.onPull(Math.abs(sobre) / ancho);

}

}

scrollX = leftBound;

} else if (scrollX > rightBound) {

if (rightAbsolute) {

float over = scrollX - rightBound;

needsInvalidate = mRightEdge.onPull(Math. abs(over) / ancho;

}

}

scrollX = rightBound;

}

//No pierdas el componente circular

mLastMotionX += scrollX - (int) scrollX;

scrollTo((int) scrollX, getScrollY( )) ;

pageScrolled((int) scrollX);

//dad por jcodecraeer

pageOffset flotante final = scrollX / ancho;

if(mFollowViewPager!=scrollTo( (int)(pageOffset*mFollowViewPager.getWidth()), mFollowViewPager.getScrollY());

}

return needInvalidate;

}

No es suficiente manejar la traducción del dedo antes de que salga de la pantalla. Después de soltar el dedo, ViewPager continuará moviéndose a una cierta distancia. , por lo que mFollowViewPager también debería seguir el movimiento. Pensemos en ello, ¿deberíamos manejar MotionEvent.ACTION_UP cuando se suelta el dedo?

Encontramos el código relevante:

case MotionEvent. ACTION_UP:

if (mIsBeingDragged) {

Final VelocityTracker velocidadTracker = mVelocityTracker;

velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);

int inicialVelocity = (int) VelocityTrackerCompat .getXVelocity(

velocityTracker, mActivePointerId);

mPopulatePending = true;

final int width = getWidth(); p>

final int scrollX = getScrollX();

final ItemInfo ii = infoForCurrentScrollPosition();

final int currentPage = ii .position

final float pageOffset = ((( float) scrollX / ancho) - ii.offset) / ii.widthFactor;

final int activePointerIndex =

MotionEventCompat.findPointerIndex(ev, mActivePointerId);

final float x =

MotionEventCompat.getX(ev, activePointerIndex);

final int totalDelta = (int) (x - mInitialMotionX);

int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity,

totalDelta);

setCurrentItemInternal(nextPage, true, true, initialVelocity

); ActivePointerId = INVALID_POINTER;

endDrag();

needsInvalidate = mLeftEdge.onRelease() | mRightEdge.onRelease();

}

Como puede verse, setCurrentIte

mInternal llama a scrollToItem(item, smoothScroll, speed, despachoSelected para lograr el efecto de continuar desplazandose después de soltar el dedo); En otras palabras, para mFollowViewPager, si llamamos a setCurrentItemInternal al mismo tiempo, podemos dejar que continúe moviéndose. En esta línea, reescribimos case

fragmento MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:

if (mIsBeingDragged) {

Final VelocityTracker speedTracker = mVelocityTracker ;

velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);

int inicialVelocity = (int) VelocityTrackerCompat.getXVelocity(