Original address: http://blog.csdn.net /sunnyfans/article/details/17969531
Question: Adopt Surface to achieve multi-touch zoom, drag display function.
- publicclassMySurfaceView3extends SurfaceViewimplements
- SurfaceHolder.Callback, OnTouchListener {
- privatestaticfinalintNONE=0;// Original
- privatestaticfinalintDRAG=1;// Drag
- privatestaticfinal
intZOOM= 2< span style="margin:0px; padding:0px; border:none; background-color:inherit">;// zoom in -
private span>int< span style="margin:0px; padding:0px; border:none; background-color:inherit">mStatus=NONE; - privatestaticfinalfloatMAX_ZOOM_SCALE=4.0f; span>
- privatestaticfinalfloatMIN_ZOOM_SCALE=1.0f;
- privatestaticfinalfloat FLOAT_TYPE=1.0f;
- privatefloatmCurrentMaxScale=MAX_ZOOM_SCALE;
- privatefloatmCurrentScale=1.0f;
- privateRect mRectSrc=new Rect();//used for render image.
- private Rect mRectDes=new Rect();// used for store size of monitor.
- privateint< /span>mCenterX,mCenterY;
- intmSurfaceHeight, mSurfaceWidth, mImageHeight, mImageWidth;
- span class=”keyword” style=”margin:0px; padding:0px; border:none; color:rgb(0,102,153); font-weight:bold; background-color:inherit”>privatePointFmStartPoint=newPointF( );
- privatefloatmStartDistance= 0f; span>
- private SurfaceHolder mSurHolder=null;
- privateBitmap mBitmap; /span>
- publicMySurfaceView3(Contextcontext,AttributeSetattrs){< /span>
- super (context,attrs);
- mSurHolder = GetHolder();
- mSurHolder.addCallback(this);
- this.setOnTouchListener(this);
- privatevoid init() {
- mCurrentMaxScale = Math.max(
- MIN_ZOOM_SCALE,
- 4 * Math.min(FLOAT_TYPE * mImageHeight / mSurfaceHeight, 1.0f
- * mImageWidth / mSurfaceWidth));
- mCurrentScale = MIN_ZOOM_SCALE;
- mCenterX = mImageWidth / 2;
- mCenterY = mImageHeight / 2;
- calcRect();
- }
- private void adjustCen ter() {
- int w = mRectSrc.right – mRectSrc.left;
- int h = mRectSrc.bottom – mRectSrc.top;
- if (mCenterX – w / 2 < 0) {
- mCenterX = w / 2;
- mRectSrc.left = 0;
- mRectSrc.right = w;
- } else if (mCenterX + w / 2 >= mImageWidth) {
- mCenterX = mImageWidth – w / 2;
- mRectSrc.right = mImageWidth;
- mRectSrc.left = mRectSrc.right – w;
-
- } else {
- mRectSrc.left = mCenterX – w / 2;
- mRectSrc.right = mRectSrc.left + w;
- }
- if (mCenterY – h / 2 < 0) {
- mCenterY = h / 2;
- mRectSrc.top = 0;
- mRectSrc.bottom = h;
- } else if (mCenterY + h / 2 >= mImageHeight) {
- mCenterY = mImageHeight – h / 2;
- mRectSrc.bottom = mImageHeight;
- mRectSrc.top = mRectSrc.bottom – h;
- } else {
- mRectSrc.top = mCenterY – h / 2;
- mRectSrc.bottom = mRectSrc.top + h;
- }
- }
- private void calcRect() {
- int w, h;
- float imageRatio, surfaceRatio;
- imageRatio = FLOAT_TYPE * mImageWidth / mImageHeight;
- surfaceRatio = FLOAT_TYPE * mSurfaceWidth / mSurfaceHeight;
- if (imageRatio < surfaceRatio) {
- h = mSurfaceHeight;
- w = (int) (h * imageRatio);
- } else {
- w = mSurfaceWidth;
- h = (int) (w / imageRatio);
- }
- if (mCurrentScale > MIN_ZOOM_SCALE) {
- w = Math.min(mSurfaceWidth, (int) (w * mCurrentScale));
- h = Math.min(mSurfaceHeight, (int) (h * mCurrentScale));
- } else {
- mCurrentScale = MIN_ZOOM_SCALE;
- }
- mRectDes.left = (mSurfaceWidth – w) / 2;
- mRectDes.top = (mSurfaceHeight – h) / 2;
- mRectDes.right = mRectDes.left + w;
- mRectDes.bottom = mRectDes.top + h;
- float curImageRatio = FLOAT_TYPE * w / h;
- int h2, w2;
- if (curImageRatio > imageRatio) {
- h2 = (int) (mImageHeight / mCurrentScale);
- w2 = (int) (h2 * curImageRatio);
- } else {
- w2 = (int) (mImageWidth / mCurrentScale);
- h2 = (int) (w2 / curImageRatio);
- }
- mRectSrc.left = mCenterX – w2 / 2;
- mRectSrc.top = mCenterY – h2 / 2;
- mRectSrc.right = mRectSrc.left + w2;
- mRectSrc.bottom = mRectSrc.top + h2;
- }
- public void setMaxZoom(float value) {
- mCurrentMaxScale = value;
- }
- public void setBitmap(Bitmap b) {
- if (b == null) {
- return;
- }
- synchronized (MySurfaceView3.class) {
- mBitmap = b;
- if (mImageHeight != mBitmap.getHeight()
- || mImageWidth != mBitmap.getWidth()) {
- mImageHeight = mBitmap.getHeight();
- mImageWidth = mBitmap.getWidth();
- init();
- }
- showBitmap();
- }
- }
- private void showBitmap() {
- synchronized (MySurfaceView3.class) {
- Canvas c = getHolder().lockCanvas();
- if (c != null && mBitmap != null) {
- c.drawColor(Color.GRAY);
- c.drawBitmap(mBitmap, mRectSrc, mRectDes, null);
- getHolder().unlockCanvasAndPost(c);
- }
- }
-
} - private void dragAction(MotionEvent event) {
- synchronized (MySurfaceView3.class) {
- PointF currentPoint = new PointF();
- currentPoint.set(event.getX(), event.getY());
- int offsetX = (int) currentPoint.x – (int) mStartPoint.x;
- int offsetY = (int) currentPoint.y – (int) mStartPoint.y;
- mStartPoint = currentPoint;
- mCenterX -= offsetX;
- mCenterY -= offsetY;
- adjustCenter();
- showBitmap();
- }
- }
- private void zoomAcition(MotionEvent event) {
- synchronized (MySurfaceView3.class) {
- float newDist = spacing(event);
- float scale = newDist / mStartDistance;
- mStartDistance = newDist;
- mCurrentScale *= scale;
- mCurrentScale = Math.max(FLOAT_TYPE,
- Math.min(mCurrentScale, mCurrentMaxScale));
- calcRect();
- adjustCenter();
- showBitmap();
- }
- }
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- switch (event.getAction() & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN:
- mStartPoint.set(event.getX(), event.getY());
- mStatus = DRAG;
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- float distance = spacing(event);
- if (distance > 10f) {
- mStatus = ZOOM;
- mStartDistance = distance;
- }
- break;
- case MotionEvent.ACTION_MOVE:
- if (mStatus == DRAG) {
- dragAction(event);
- } else {
- if (event.getPointerCount() == 1)
- return true;
- zoomAcition(event);
- }
- b reak;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP:
- mStatus = NONE;
- break;
- default:
- break;
- }
- return t rue;
- }
- private float spacing(MotionEvent event) {
- float x = event.getX(0) – event.getX(1);
- float y = event.getY(0) – event.getY(1);
- return (float) Math.sqrt(x * x + y * y);
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- // TODO Auto-generated method stub
- }
- // 初始化
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
- synchronized (MySurfaceView3.class) {
- mRectDes.set(0, 0, width, height);
- mSurfaceHeight = height;
- mSurfaceWidth = width;
- init();
- if (mBitmap != null) {
- showBitmap();
- }
- }
- }
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- }
- }
< li class="alt" style="border-style:none none none solid; border-left-width:3px; border-left-color:rgb(108,226,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important">
- public class MySurfaceView3 extends SurfaceView implements
- SurfaceHolder.Callback, OnTouchListener {
- private static final int NONE = 0;// 原始
- private static final int DRAG = 1;// 拖动
-
private static final int ZOOM = 2;// 放大 - private int mStatus = NONE;
- private static final float MAX_ZOOM_SCALE = 4.0f;
- private static final float MIN_ZOOM_SCALE = 1.0f;
- private static final float FLOAT_TYPE = 1.0f;
- private float mCurrentMaxScale = MAX_ZOOM_SCALE;
- private float mCurrentScale = 1.0f;
- private Rect mRectSrc = new Rect(); // used for render image.
- private Rect mRectDes = new Rect(); // used for store size of monitor.
- private int mCenterX, mCenterY;
- int mSurfaceHeight, mSurfaceWidth, mImageHeight, mImageWidth;
- private PointF mStartPoint = new PointF();
- private float mStartDistance = 0f;
- private SurfaceHolder mSurHolder = null;
- private Bitmap mBitmap;
- public MySurfaceView3(Context context, AttributeSet attrs) {
- super(context, attrs);
- mSurHolder = getHolder();
- mSurHolder.addCallback(this);
- this.setOnTouchListener(this);
- }
- private void init() {
- mCurrentMaxScale = Math.max(
- MIN_ZOOM_SCALE,
- 4 * Math.min(FLOAT_TYPE * mImageHeight / mSurfaceHeight, 1.0f
- * mImageWidth / mSurfaceWidth));
- mCurrentScale = MIN_ZOOM_SCALE;
- mCenterX = mImageWidth / 2;
- mCenterY = mImageHeight / 2;
- calcRect();
- }
- private void adjustCenter() {
- int w = mRectSrc.right – mRectSrc.left;
- int h = mRectSrc.bottom – mRectSrc.top;
- if (mCenterX – w / 2 < 0) {
- mCenterX = w / 2;
- mRectSrc.left = 0;
- mRectSrc.right = w;
- } else if (mCenterX + w / 2 >= mImageWidth) {
- mCenterX = mImageWidth – w / 2;
- mRectSrc.right = mImageWidth;
- mRectSrc.left = mRectSrc.right – w;
- } else {
- mRectSrc.left = mCenterX – w / 2;
- mRectSrc.right = mRectSrc.left + w;
- }
- if (mCenterY – h / 2 < 0) {
- mCenterY = h / 2;
- mRectSrc.top = 0;
- mRectSrc.bottom = h;
- } else if (mCenterY + h / 2 >= mImageHeight) {
- mCenterY = mImageHeight – h / 2;
- mRectSrc.bottom = mImageHeight;
- mRectSrc.top = mRectSrc.bottom – h;
- } else {
- mRectSrc.top = mCenterY – h / 2;
- mRectSrc.bottom = mRectSrc.top + h;
- }
- }
- private void calcRect() {
- int w, h;
- float imageRatio, surfaceRatio;
- imageRatio = FLOAT_TYPE * mImageWidth / mImageHeight;
- surfaceRatio = FLOAT_TYPE * mSurfaceWidth / mSurfaceHeight;
- if (imageRatio < surfaceRatio) {
- h = mSurfaceHeight;
- w = (int) (h * imageRatio);
- } else {
- w = mSurfaceWidth;
- h = (int) (w / imageRatio);
- }
- if (mCurrentScale > MIN_ZOOM_SCALE) {
- w = Math.min(mSurfaceWidth, (int) (w * mCurrentScale));
- h = Math.min(mSurfaceHeight, (int) (h * mCurrentScale));
- } else {
- mCurrentScale = MIN_ZOOM_SCALE;
- }
- mRectDes.left = (mSurfaceWidth – w) / 2;
- mRectDes.top = (mSurfaceHeight – h) / 2;
- mRectDes.right = mRectDes.left + w;
- mRectDes.bottom = mRectDes.top + h;
- float curImageRatio = FLOAT_TYPE * w / h;
- int h2, w2;
- if (curImageRatio > imageRatio) {
- h2 = (int) (mImageH eight / mCurrentScale);
- w2 = (int) (h2 * curImageRatio);
- } else {
- w2 = (
int ) (mImageWidth / mCurrentScale); - h2 = (int) (w2 / curImageRatio);
- }
- mRectSrc.left = mCenterX – w2 / 2;
- mRectSrc.top = mCenterY – h2 / 2;
- mRectSrc.right = mRectSrc.left + w2;
- mRectSrc.bottom = mRectSrc.top + h2;
- }
- public void setMaxZoom(float value) {
- mCurrentMaxScale = value;
- }
- public void setBitmap(Bitmap b) {
- if (b == null) {
- return;
- }
- synchronized (MySurfaceView3.class) {
- mBitmap = b;
- if (mImageHeight != mBitmap.getHeight()
- || mImageWidth != mBitmap.getWidth()) {
- mImageHeight = mBitmap.getHeight();
- mImageWidth = mBitmap.getWidth();
- init();
- }
- showBitmap();
- }
- }
- private void showBitmap() {
- synchronized (MySurfaceView3.class) {
- Canvas c = getHolder().lockCanva s();
- if (c != null && mBitmap != null) {
- c.drawColor(Color.GRAY);
- c.drawBitmap(mBitmap, mRectSrc, mRectDes, null);
- getHolder().unlockCanvasAndPost(c);
- }
- }
- }
- private void dragAction(MotionEvent event) {
- synchronized (MySurfaceView3.class) {
- PointF currentPoint = new PointF();
- currentPoint.set(event.getX(), event.getY());
- int offsetX = (int) currentPoint.x – (int) mStartPoint.x;
- int offsetY = (int) currentPoint.y – (int) mStartPoint.y;
- mStartPoint = currentPoint;
- mCenterX -= offsetX;
- mCenterY -= offsetY;
- adjustCenter();
- showBitmap ();
- }
- }
- private void zoomAcition(MotionEvent event) {
- synchronized (MySurfaceView3.class) {
- float newDist = spacing(event);
- float scale = newDist / mStartDistance;
- mStartDistance = newDist;
- mCurrentScale *= scale;
- mCurrentScale = Math.max(FLOAT_TYPE,
- Math.min(mCurrentScale, mCurrentMaxScale));
- calcRect();
- adjustCenter();
- showBitmap();
- }
- }
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- switch (event.getAction() & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN:
- mStartPoint.set(event.getX(), event.getY());
- mStatus = DRAG;
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- float distance = spacing(event);
- if (distance > 10f) {
- mStatus = ZOOM;
- mStartDistance = distance;
- }
- break;
- case MotionEvent.ACTION_MOVE:
- if (mStatus == DRAG) {
- dragAction(event);
- } else {
- if (event.getPointerCount() == 1)
- return true;
- zoomAcition(event);
- }
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP:
- mStatus = NONE;
- break;
- default:
- break;
- }
- return true;
- }
- private float spacing(MotionEvent event) {
- float x = event.getX(0) – event.getX(1);
- float y = event.getY(0) – event.getY(1);
- return (float) Math.sqrt(x * x + y * y);
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- // TODO Auto-generated method stub
- }
- // 初始化
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
- synchronized (MySurfaceView3.class) {
- mRectDes.set(0, 0, width, height);
- mSurfaceHeight = height;
- mSurfaceWidth = width;
- init();
- if (mBitmap != null) {
-
showBitmap(); - }
- }
- }
- @Override
- public void surfaceDestroyed( SurfaceHolder holder) {
- }
- }
[java] view plain copy