2014-09-11 94 views

回答

0

有一些庫,你可以實現捏縮放。請檢查網頁。

+0

哈哈感謝您的偉大建議 – Raghavender 2014-09-11 07:21:11

-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); 
    } 
} 
+0

我正在嘗試使用此佈局。由於這是一個框架佈局,我在圖片的頂部放置了更多的文字視圖,這些文字視圖應該放大與圖像視圖相同的比例。但textview的縮放比例與imageview的不同。欣賞任何指導。 – techtinkerer 2016-03-17 22:23:21

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

答案和簡單的解決方案 – 2017-01-14 20:07:32