android android-recyclerview pinchzoom android-touch-event

Android change recycler view column no. en el zoom de pellizco



android-recyclerview pinchzoom (2)

Esta es la manera de entrar y salir, ya lo he comprobado en mi aplicación de ejemplo funcionando correctamente.

import android.content.Context; import android.graphics.Canvas; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ScaleGestureDetector; /** @author yogesh * */ public class PinchRecyclerView extends RecyclerView { private static final int INVALID_POINTER_ID = -1; private int mActivePointerId = INVALID_POINTER_ID; private ScaleGestureDetector mScaleDetector; private float mScaleFactor = 1.f; private float maxWidth = 0.0f; private float maxHeight = 0.0f; private float mLastTouchX; private float mLastTouchY; private float mPosX; private float mPosY; private float width; private float height; public PinchRecyclerView(Context context) { super(context); if (!isInEditMode()) mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); } public PinchRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); if (!isInEditMode()) mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); } public PinchRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); if (!isInEditMode()) mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { width = MeasureSpec.getSize(widthMeasureSpec); height = MeasureSpec.getSize(heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { try { return super.onInterceptTouchEvent(ev); } catch (IllegalArgumentException ex) { ex.printStackTrace(); } return false; } @Override public boolean onTouchEvent(@NonNull MotionEvent ev) { super.onTouchEvent(ev); final int action = ev.getAction(); mScaleDetector.onTouchEvent(ev); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { final float x = ev.getX(); final float y = ev.getY(); mLastTouchX = x; mLastTouchY = y; mActivePointerId = ev.getPointerId(0); break; } case MotionEvent.ACTION_MOVE: { /* this line is replaced because here came below isssue java.lang.IllegalArgumentException: pointerIndex out of range ref http://stackoverflow.com/questions/6919292/pointerindex-out-of-range-android-multitouch */ //final int pointerIndex = ev.findPointerIndex(mActivePointerId); final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; final float x = ev.getX(pointerIndex); final float y = ev.getY(pointerIndex); final float dx = x - mLastTouchX; final float dy = y - mLastTouchY; mPosX += dx; mPosY += dy; if (mPosX > 0.0f) mPosX = 0.0f; else if (mPosX < maxWidth) mPosX = maxWidth; if (mPosY > 0.0f) mPosY = 0.0f; else if (mPosY < maxHeight) mPosY = maxHeight; mLastTouchX = x; mLastTouchY = y; invalidate(); break; } case MotionEvent.ACTION_UP: { mActivePointerId = INVALID_POINTER_ID; break; } case MotionEvent.ACTION_CANCEL: { mActivePointerId = INVALID_POINTER_ID; break; } case MotionEvent.ACTION_POINTER_UP: { final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; final int pointerId = ev.getPointerId(pointerIndex); if (pointerId == mActivePointerId) { final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mLastTouchX = ev.getX(newPointerIndex); mLastTouchY = ev.getY(newPointerIndex); mActivePointerId = ev.getPointerId(newPointerIndex); } break; } } return true; } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.translate(mPosX, mPosY); canvas.scale(mScaleFactor, mScaleFactor); canvas.restore(); } @Override protected void dispatchDraw(@NonNull Canvas canvas) { canvas.save(Canvas.MATRIX_SAVE_FLAG); if (mScaleFactor == 1.0f) { mPosX = 0.0f; mPosY = 0.0f; } canvas.translate(mPosX, mPosY); canvas.scale(mScaleFactor, mScaleFactor); super.dispatchDraw(canvas); canvas.restore(); invalidate(); } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { mScaleFactor *= detector.getScaleFactor(); mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 3.0f)); maxWidth = width - (width * mScaleFactor); maxHeight = height - (height * mScaleFactor); invalidate(); return true; } } }

Tengo en mi vista de reciclado de diseño para la aplicación de galería.

Quiero incorporar un selector de eventos táctiles pellizco de tal manera que la columna de vista de reciclador no. aumenta o disminuye en pich dentro y fuera.

He visto este tipo de interfaz en muchas aplicaciones de galería.

Cuál es la mejor manera de lograr esto para que la transición sea fluida.

Pequeño enlace de video: - http://sendvid.com/s68fiqpd

Intenté usar el código siguiente (proporcionado por @Yogesh Rathi), pero los resultados no son lo que quiero lograr.

import android.content.Context; import android.graphics.Canvas; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ScaleGestureDetector; /** @author yogesh * */ public class PinchRecyclerView extends RecyclerView { private static final int INVALID_POINTER_ID = -1; private int mActivePointerId = INVALID_POINTER_ID; private ScaleGestureDetector mScaleDetector; private float mScaleFactor = 1.f; private float maxWidth = 0.0f; private float maxHeight = 0.0f; private float mLastTouchX; private float mLastTouchY; private float mPosX; private float mPosY; private float width; private float height; public PinchRecyclerView(Context context) { super(context); if (!isInEditMode()) mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); } public PinchRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); if (!isInEditMode()) mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); } public PinchRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); if (!isInEditMode()) mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { width = MeasureSpec.getSize(widthMeasureSpec); height = MeasureSpec.getSize(heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { try { return super.onInterceptTouchEvent(ev); } catch (IllegalArgumentException ex) { ex.printStackTrace(); } return false; } @Override public boolean onTouchEvent(@NonNull MotionEvent ev) { super.onTouchEvent(ev); final int action = ev.getAction(); mScaleDetector.onTouchEvent(ev); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { final float x = ev.getX(); final float y = ev.getY(); mLastTouchX = x; mLastTouchY = y; mActivePointerId = ev.getPointerId(0); break; } case MotionEvent.ACTION_MOVE: { /* this line is replaced because here came below isssue java.lang.IllegalArgumentException: pointerIndex out of range ref http://stackoverflow.com/questions/6919292/pointerindex-out-of-range-android-multitouch */ //final int pointerIndex = ev.findPointerIndex(mActivePointerId); final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; final float x = ev.getX(pointerIndex); final float y = ev.getY(pointerIndex); final float dx = x - mLastTouchX; final float dy = y - mLastTouchY; mPosX += dx; mPosY += dy; if (mPosX > 0.0f) mPosX = 0.0f; else if (mPosX < maxWidth) mPosX = maxWidth; if (mPosY > 0.0f) mPosY = 0.0f; else if (mPosY < maxHeight) mPosY = maxHeight; mLastTouchX = x; mLastTouchY = y; invalidate(); break; } case MotionEvent.ACTION_UP: { mActivePointerId = INVALID_POINTER_ID; break; } case MotionEvent.ACTION_CANCEL: { mActivePointerId = INVALID_POINTER_ID; break; } case MotionEvent.ACTION_POINTER_UP: { final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; final int pointerId = ev.getPointerId(pointerIndex); if (pointerId == mActivePointerId) { final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mLastTouchX = ev.getX(newPointerIndex); mLastTouchY = ev.getY(newPointerIndex); mActivePointerId = ev.getPointerId(newPointerIndex); } break; } } return true; } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.translate(mPosX, mPosY); canvas.scale(mScaleFactor, mScaleFactor); canvas.restore(); } @Override protected void dispatchDraw(@NonNull Canvas canvas) { canvas.save(Canvas.MATRIX_SAVE_FLAG); if (mScaleFactor == 1.0f) { mPosX = 0.0f; mPosY = 0.0f; } canvas.translate(mPosX, mPosY); canvas.scale(mScaleFactor, mScaleFactor); super.dispatchDraw(canvas); canvas.restore(); invalidate(); } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { mScaleFactor *= detector.getScaleFactor(); mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 3.0f)); maxWidth = width - (width * mScaleFactor); maxHeight = height - (height * mScaleFactor); invalidate(); return true; } } }

Gracias


Puede usar el detector de gestos de escala junto con los administradores de disposición en la vista de reciclado para lograr esto. configura el detector táctil en tu vista de reciclador y pasa el evento táctil a una instancia del detector de gestos de escala. En la función onScale () puede alternar los administradores de diseños para su vista de reciclador en función del factor de escala. He creado una demostración para esto. Puedes encontrar el código aquí