如何在ANDROID View Pager中缩放/捏合Total FrameLayout

时间:2014-09-11 06:59:39

标签: android

我正在研究View寻呼机概念,Frame Layout是视图寻呼机适配器的膨胀视图,在帧布局中我有4个图像视图显示在每个视图寻呼机页面上,现在如何缩放/捏合具有4个图像视图的总视图寻呼机dispaly。

3 个答案:

答案 0 :(得分:1)

您可以将此自定义imageview类用于“缩放缩放图像”视图:

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;
/**
*
* @author Vinil.S
*
*/
public class RiktamImageView 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 RiktamImageView(Context context) {
super(context);
sharedConstructing(context);
}

public RiktamImageView(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();

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();
}
}

答案 1 :(得分:0)

有些库可以实现捏缩放。请查看网页。

答案 2 :(得分:-1)

Here 是在android framelayout中启用缩放/缩放的类。

<强>代码:

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.FrameLayout;

 /**
 * Layout that provides pinch-zooming of content. This view should have exactly one child
 * view containing the content.
 */
public class ZoomLayout extends FrameLayout implements ScaleGestureDetector.OnScaleGestureListener {

  private enum Mode {
    NONE,
    DRAG,
    ZOOM
  }

  private static final String TAG = "ZoomLayout";
  private static final float MIN_ZOOM = 1.0f;
  private static final float MAX_ZOOM = 4.0f;

  private Mode mode = Mode.NONE;
  private float scale = 1.0f;
  private float lastScaleFactor = 0f;

  // Where the finger first  touches the screen
  private float startX = 0f;
  private float startY = 0f;

  // How much to translate the canvas
  private float dx = 0f;
  private float dy = 0f;
  private float prevDx = 0f;
  private float prevDy = 0f;

  public ZoomLayout(Context context) {
    super(context);
    init(context);
  }

  public ZoomLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
  }

  public ZoomLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
  }

  private void init(Context context) {
    final ScaleGestureDetector scaleDetector = new ScaleGestureDetector(context, this);
    this.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View view, MotionEvent motionEvent) {
        switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
          case MotionEvent.ACTION_DOWN:
            Log.i(TAG, "DOWN");
            if (scale > MIN_ZOOM) {
              mode = Mode.DRAG;
              startX = motionEvent.getX() - prevDx;
              startY = motionEvent.getY() - prevDy;
            }
            break;
          case MotionEvent.ACTION_MOVE:
            if (mode == Mode.DRAG) {
              dx = motionEvent.getX() - startX;
              dy = motionEvent.getY() - startY;
            }
            break;
          case MotionEvent.ACTION_POINTER_DOWN:
            mode = Mode.ZOOM;
            break;
          case MotionEvent.ACTION_POINTER_UP:
            mode = Mode.DRAG;
            break;
          case MotionEvent.ACTION_UP:
            Log.i(TAG, "UP");
            mode = Mode.NONE;
            prevDx = dx;
            prevDy = dy;
            break;
        }
        scaleDetector.onTouchEvent(motionEvent);

        if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
          getParent().requestDisallowInterceptTouchEvent(true);
          float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
          float maxDy = (child().getHeight() - (child().getHeight() / scale))/ 2 * scale;
          dx = Math.min(Math.max(dx, -maxDx), maxDx);
          dy = Math.min(Math.max(dy, -maxDy), maxDy);
          Log.i(TAG, "Width: " + child().getWidth() + ", scale " + scale + ", dx " + dx
            + ", max " + maxDx);
          applyScaleAndTranslation();
        }

        return true;
      }
    });
  }

  // ScaleGestureDetector

  @Override
  public boolean onScaleBegin(ScaleGestureDetector scaleDetector) {
    Log.i(TAG, "onScaleBegin");
    return true;
  }

  @Override
  public boolean onScale(ScaleGestureDetector scaleDetector) {
    float scaleFactor = scaleDetector.getScaleFactor();
    Log.i(TAG, "onScale" + scaleFactor);
    if (lastScaleFactor == 0 || (Math.signum(scaleFactor) == Math.signum(lastScaleFactor))) {
      scale *= scaleFactor;
      scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));
      lastScaleFactor = scaleFactor;
    } else {
      lastScaleFactor = 0;
    }
    return true;
  }

  @Override
  public void onScaleEnd(ScaleGestureDetector scaleDetector) {
    Log.i(TAG, "onScaleEnd");
  }

  private void applyScaleAndTranslation() {
    child().setScaleX(scale);
    child().setScaleY(scale);
    child().setTranslationX(dx);
    child().setTranslationY(dy);
  }

  private View child() {
    return getChildAt(0);
  }
}