You can learnd some zooming/panning knowledge from link below.
http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2/1747
Then you will want to know how to add scale limit and pan bounds, and the answer is as follow link.
http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-6-implementing-the-pinch-zoom-gesture/1847
Maybe you want to built-in the zooming/panning function in a ImageView.
http://code.google.com/p/4chan-image-browser/source/browse/src/se/robertfoss/MultiTouchZoom/TouchImageView.java?r=02836650d3b69dd6a2fce1304c34ded1531d6ad5
http://code.google.com/p/4chan-image-browser/source/browse/src/se/robertfoss/MultiTouchZoom/WrapMotionEvent.java?r=c1ea13ef76d6f3ec6024cecf4a6db68e42030916
We all want to watch pictures in a scroll view as Gallery, but the OnTouch event will conflict with OnScroll and OnFling event.
I try to work it out by evaluate if the image bound cross over the bound of container, then raise OnKeyDown event when reach the condition.
In order to avoid the TouchImageView intercept the OnTouch event, so built-in the multi-touch function in Gallery view.
Maybe we want to click on a image to retrieve original size, so I expend the multi-touch mode with "TAP" to reset the matrix.
The source code of "GalleryEx" as below
============================================
package com.example.twnin;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.*;
import android.widget.Gallery;
import android.widget.ImageView;
public class GalleryEx extends Gallery
{
private Context m_Context;
private int m_horizontalMargin;
private int m_verticalMargin;
//variables for zoom limit and pan bounds
private float[] m_matrixValues = new float[9];
private float m_maxZoom = 2f;
private float m_minZoom = 0.75f;
private RectF m_viewRect;
//variables for multi-touch
private Matrix m_matrix = new Matrix();
private Matrix m_savedMatrix = new Matrix();
static final int NONE = 0;
static final int TAP = 1;
static final int DRAG = 2;
static final int ZOOM = 3;
int m_mode = NONE;
private PointF m_start = new PointF();
private PointF m_mid = new PointF();
private float m_oldDist = 1f;
private int m_eventPageIndex = 0;
MotionEvent m_startEvent;
public GalleryEx(Context context)
{
super(context);
m_Context = context;
}
public void setImageHorizontalMargin(int horizontalMargin)
{
m_horizontalMargin = horizontalMargin;
}
public void setImageVerticalMargin(int verticalMargin)
{
m_verticalMargin = verticalMargin;
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
ImageView myImageView = (ImageView) super.getSelectedView();
m_viewRect = new RectF(0, 0, myImageView.getWidth(), myImageView.getHeight());
switch (event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
m_savedMatrix.set(m_matrix);
m_start.set(event.getX(), event.getY());
m_startEvent = MotionEvent.obtain(event);
m_mode = TAP;
m_eventPageIndex = myImageView.getId();
break;
case MotionEvent.ACTION_POINTER_DOWN:
m_oldDist = spacing(event);
if (m_oldDist > 10f)
{
m_savedMatrix.set(m_matrix);
midPoint(m_mid, event);
m_mode = ZOOM;
}
break;
case MotionEvent.ACTION_UP:
if (m_mode == TAP)
{
// do something when user click
m_matrix.reset();
m_mode = NONE;
}
onScroll(m_startEvent, event, myImageView.getLeft()-25, 0);
break;
case MotionEvent.ACTION_POINTER_UP:
m_mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
if (m_mode == TAP || m_mode == DRAG)
{
// if page changed then return
if (m_eventPageIndex != myImageView.getId())
{
m_matrix.reset();
this.setSelection(myImageView.getId());
return true;
}
m_mode = DRAG;
m_matrix.set(m_savedMatrix);
// limit pan boundary
m_matrix.getValues(m_matrixValues);
float currentY = m_matrixValues[Matrix.MTRANS_Y];
float currentX = m_matrixValues[Matrix.MTRANS_X];
float currentScale = m_matrixValues[Matrix.MSCALE_X];
float currentHeight = myImageView.getHeight() * currentScale;
float currentWidth = myImageView.getWidth() * currentScale;
float dx = event.getX() - m_start.x;
float dy = event.getY() - m_start.y;
float newX = currentX+dx;
float newY = currentY+dy;
RectF drawingRect = new RectF(newX, newY, newX+currentWidth, newY+currentHeight);
float diffUp = Math.min(m_viewRect.bottom-drawingRect.bottom, m_viewRect.top-drawingRect.top);
float diffDown = Math.max(m_viewRect.bottom-drawingRect.bottom, m_viewRect.top-drawingRect.top);
float diffLeft = Math.min(m_viewRect.left-drawingRect.left, m_viewRect.right-drawingRect.right);
float diffRight = Math.max(m_viewRect.left-drawingRect.left, m_viewRect.right-drawingRect.right);
if(diffUp > 0)
{
dy += diffUp;
}
if(diffDown < 0)
{
dy += diffDown;
}
if(diffLeft > 0)
{
dx += diffLeft;
}
if(diffRight < 0)
{
dx += diffRight;
}
m_matrix.postTranslate(dx, dy);
// if image exceed boundary then scroll, otherwise align center
if(currentWidth < myImageView.getWidth())
{
if(newX < -m_horizontalMargin)
{
float offset = -newX - (600 - myImageView.getRight());
onScroll(m_startEvent, event, offset, 0);
}
else if (newX + currentWidth > myImageView.getWidth() + m_horizontalMargin)
{
float offset = -(newX + currentWidth - myImageView.getWidth()) - (0 - myImageView.getLeft());
onScroll(m_startEvent, event, offset, 0);
}
else
{
onScroll(m_startEvent, event, myImageView.getLeft() - m_horizontalMargin, 0);
}
}
else
{
if (newX + currentWidth <= myImageView.getWidth())
{
float offset = -(newX + currentWidth - myImageView.getWidth()) - (600 - myImageView.getRight());
onScroll(m_startEvent, event, offset, 0);
}
else if (newX > 0)
{
float offset = -newX - (0 - myImageView.getLeft());
onScroll(m_startEvent, event, offset, 0);
}
else
{
onScroll(m_startEvent, event, myImageView.getLeft() - m_horizontalMargin, 0);
}
}
}
else if (m_mode == ZOOM)
{
float newDist = spacing(event);
if (newDist > 10f)
{
m_matrix.set(m_savedMatrix);
float scale = newDist / m_oldDist;
// limit zoom
m_matrix.getValues(m_matrixValues);
float currentScale = m_matrixValues[Matrix.MSCALE_X];
if (scale * currentScale > m_maxZoom)
{
scale = m_maxZoom / currentScale;
}
else if (scale * currentScale < m_minZoom)
{
scale = m_minZoom / currentScale;
}
m_matrix.postScale(scale, scale, m_mid.x, m_mid.y);
}
}
}
myImageView.setImageMatrix(m_matrix);
return true;
}
/** Determine the space between the first two fingers */
private float spacing(MotionEvent event)
{
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
/** Calculate the mid point of the first two fingers */
private void midPoint(PointF point, MotionEvent event)
{
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
}
gr8 job done ...........it is really a helpful document..........thanks
回覆刪除Sorry, when I tried it, I find it not stable when scrolling. Can I ask:
回覆刪除1. what is setting the horizontalMargin and verticalMargin?
2. what scaleType are the images?
3. how are the images loaded? via ImageAdapter?