programar para pantalla hacer gestos aplicacion android

pantalla - ¿Podemos usar el detector de gesto de escala para el zoom de pellizco en Android?



programar gestos en android (6)

Puede crear una clase reutilizable que implemente OnTouchListener para lograr esto.

public class MyScaleGestures implements OnTouchListener, OnScaleGestureListener { private View view; private ScaleGestureDetector gestureScale; private float scaleFactor = 1; public StandardGestures(Context c){ gestureScale = new ScaleGestureDetector(c, this); } @Override public boolean onTouch(View view, MotionEvent event) { this.view = view; gestureScale.onTouchEvent(event); return true; } @Override public boolean onScale(ScaleGestureDetector detector) { scaleFactor *= detector.getScaleFactor(); scaleFactor = (scaleFactor < 1 ? 1 : scaleFactor); // prevent our view from becoming too small // scaleFactor = ((float)((int)(scaleFactor * 100))) / 100; // Change precision to help with jitter when user just rests their fingers // view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { inScale = true; return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { inScale = false; } }

Luego, OnTouchListener como OnTouchListener tu View como tal.

myView.setOnTouchListener(new MyScaleGestures(context));

Si desea agregar una capacidad de desplazamiento a la View , deberá implementar onScroll desde la interfaz de OnGestureListener . Puede agregar esta anulación a la clase MyScaleGestures para lograr esto.

@Override public boolean onScroll(MotionEvent event1, MotionEvent event2, float x, float y) { float newX = view.getX(); float newY = view.getY(); if(!inScale){ newX -= x; newY -= y; } WindowManager wm = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE); Display d = wm.getDefaultDisplay(); Point p = new Point(); d.getSize(p); if (newX > (view.getWidth() * scaleFactor - p.x) / 2){ newX = (view.getWidth() * scaleFactor - p.x) / 2; } else if (newX < -((view.getWidth() * scaleFactor - p.x) / 2)){ newX = -((view.getWidth() * scaleFactor - p.x) / 2); } if (newY > (view.getHeight() * scaleFactor - p.y) / 2){ newY = (view.getHeight() * scaleFactor - p.y) / 2; } else if (newY < -((view.getHeight() * scaleFactor - p.y) / 2)){ newY = -((view.getHeight() * scaleFactor - p.y) / 2); } view.setX(newX); view.setY(newY); return true; }

El resultado final de hacer todo lo anterior te dará una clase como esta:

public class simpleOnScaleGestureListener extends SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { startScale = detector.getScaleFactor(); return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { endScale = detector.getScaleFactor(); // if ((startScale - endScale) > 0.0100 // || (endScale - startScale) > 0.0100) { if (startScale > endScale) { Log.i("onScaleEnd", "Pinch Dection"); onPinch(); } else if (startScale < endScale) { Log.i("onScaleEnd", "Zoom Dection"); onZoom(); } // } } }

¿Podemos usar el detector de gesto de escala para el zoom de pellizco en Android?


Puedes usar esto

import android.content.Context; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; public class MyImageView extends View { private static final int INVALID_POINTER_ID = -1; private Drawable mImage; private float mPosX; private float mPosY; private float mLastTouchX; private float mLastTouchY; private int mActivePointerId = INVALID_POINTER_ID; private ScaleGestureDetector mScaleDetector; private float mScaleFactor = 1.f; public MyImageView(Context context) { this(context, null, 0); mImage=act.getResources().getDrawable(context.getResources().getIdentifier("imag­ename", "drawable", "packagename")); mImage.setBounds(0, 0, mImage.getIntrinsicWidth(), mImage.getIntrinsicHeight()); } public MyImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); } @Override public boolean onTouchEvent(MotionEvent ev) { // Let the ScaleGestureDetector inspect all events. mScaleDetector.onTouchEvent(ev); final int action = ev.getAction(); 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: { final int pointerIndex = ev.findPointerIndex(mActivePointerId); final float x = ev.getX(pointerIndex); final float y = ev.getY(pointerIndex); // Only move if the ScaleGestureDetector isn''t processing a gesture. if (!mScaleDetector.isInProgress()) { final float dx = x - mLastTouchX; final float dy = y - mLastTouchY; mPosX += dx; mPosY += dy; invalidate(); } mLastTouchX = x; mLastTouchY = y; 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 = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; final int pointerId = ev.getPointerId(pointerIndex); if (pointerId == mActivePointerId) { // This was our active pointer going up. Choose a new // active pointer and adjust accordingly. 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(); Log.d("DEBUG", "X: "+mPosX+" Y: "+mPosY); canvas.translate(mPosX, mPosY); canvas.scale(mScaleFactor, mScaleFactor); mImage.draw(canvas); canvas.restore(); } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { mScaleFactor *= detector.getScaleFactor(); // Don''t let the object get too small or too large. mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f)); invalidate(); return true; } } }

para llamar a esto en su activity.setContentView(new MyImageView(this));



TouchImageView

public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); TouchImageView img = new TouchImageView(this); img.setImageResource(R.drawable.ic_launcher); img.setMaxZoom(4f); setContentView(img); } }

MainActivity.java

public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); TouchImageView img = new TouchImageView(this); img.setImageResource(R.drawable.ic_launcher); img.setMaxZoom(4f); setContentView(img); } }


en realidad hay una biblioteca que usa esta clase solo para el zoom de imágenes.

se llama " TouchImageView "


sí, aquí podemos ver el código de ejemplo donde onPinch () y onZoom () son acciones que se implementarán por su cuenta.

public class TouchImageView extends ImageView { Matrix matrix; // We can be in one of these 3 states static final int NONE = 0; static final int DRAG = 1; static final int ZOOM = 2; int mode = NONE; // Remember some things for zooming PointF last = new PointF(); PointF start = new PointF(); float minScale = 1f; float maxScale = 3f; float[] m; int viewWidth, viewHeight; static final int CLICK = 3; float saveScale = 1f; protected float origWidth, origHeight; int oldMeasuredWidth, oldMeasuredHeight; ScaleGestureDetector mScaleDetector; Context context; public TouchImageView(Context context) { super(context); sharedConstructing(context); } public TouchImageView(Context context, AttributeSet attrs) { super(context, attrs); sharedConstructing(context); } private void sharedConstructing(Context context) { super.setClickable(true); this.context = context; mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); matrix = new Matrix(); m = new float[9]; setImageMatrix(matrix); setScaleType(ScaleType.MATRIX); setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { mScaleDetector.onTouchEvent(event); PointF curr = new PointF(event.getX(), event.getY()); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: last.set(curr); start.set(last); mode = DRAG; break; case MotionEvent.ACTION_MOVE: if (mode == DRAG) { float deltaX = curr.x - last.x; float deltaY = curr.y - last.y; float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale); float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale); matrix.postTranslate(fixTransX, fixTransY); fixTrans(); last.set(curr.x, curr.y); } break; case MotionEvent.ACTION_UP: mode = NONE; int xDiff = (int) Math.abs(curr.x - start.x); int yDiff = (int) Math.abs(curr.y - start.y); if (xDiff < CLICK && yDiff < CLICK) performClick(); break; case MotionEvent.ACTION_POINTER_UP: mode = NONE; break; } setImageMatrix(matrix); invalidate(); return true; // indicate event was handled } }); } public void setMaxZoom(float x) { maxScale = x; } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScaleBegin(ScaleGestureDetector detector) { mode = ZOOM; return true; } @Override public boolean onScale(ScaleGestureDetector detector) { float mScaleFactor = detector.getScaleFactor(); float origScale = saveScale; saveScale *= mScaleFactor; if (saveScale > maxScale) { saveScale = maxScale; mScaleFactor = maxScale / origScale; } else if (saveScale < minScale) { saveScale = minScale; mScaleFactor = minScale / origScale; } if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight) matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2); else matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY()); fixTrans(); return true; } } void fixTrans() { matrix.getValues(m); float transX = m[Matrix.MTRANS_X]; float transY = m[Matrix.MTRANS_Y]; float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale); float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale); if (fixTransX != 0 || fixTransY != 0) matrix.postTranslate(fixTransX, fixTransY); } float getFixTrans(float trans, float viewSize, float contentSize) { float minTrans, maxTrans; if (contentSize <= viewSize) { minTrans = 0; maxTrans = viewSize - contentSize; } else { minTrans = viewSize - contentSize; maxTrans = 0; } if (trans < minTrans) return -trans + minTrans; if (trans > maxTrans) return -trans + maxTrans; return 0; } float getFixDragTrans(float delta, float viewSize, float contentSize) { if (contentSize <= viewSize) { return 0; } return delta; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); viewWidth = MeasureSpec.getSize(widthMeasureSpec); viewHeight = MeasureSpec.getSize(heightMeasureSpec); // // Rescales image on rotation // if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight || viewWidth == 0 || viewHeight == 0) return; oldMeasuredHeight = viewHeight; oldMeasuredWidth = viewWidth; if (saveScale == 1) { //Fit to screen. float scale; Drawable drawable = getDrawable(); if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0) return; int bmWidth = drawable.getIntrinsicWidth(); int bmHeight = drawable.getIntrinsicHeight(); Log.e("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight); float scaleX = (float) viewWidth / (float) bmWidth; float scaleY = (float) viewHeight / (float) bmHeight; scale = Math.min(scaleX, scaleY); matrix.setScale(scale, scale); // Center the image float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight); float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth); redundantYSpace /= (float) 2; redundantXSpace /= (float) 2; matrix.postTranslate(redundantXSpace, redundantYSpace); origWidth = viewWidth - 2 * redundantXSpace; origHeight = viewHeight - 2 * redundantYSpace; setImageMatrix(matrix); } fixTrans(); } }