Enlarge and drag Bitmap in custom View in Android

Source: Internet
Author: User
Tags gety

Enlarge and drag Bitmap in custom View in Android
I. Basic Implementation ideas:

Implement the custom View-MyImageView Class Based on The View class. The OnTouchListener interface is completed in the Activity class of View to monitor and process MotionEvent events. The common MotionEvent events are as follows:

ACTION_DOWN event, recording the start point of Translation
ACTION_UP event to End translation event processing
ACTION_MOVE event: records the translation point, calculates the distance from the start point, implements Bitmap translation, and calculates the distance between two points in multi-touch mode to enlarge the image.
The ACTION_POINTER_DOWN event is used to calculate the distance between two points as the initial distance for image gesture amplification.
ACTION_POINTER_UP event, end two-point touch to enlarge Image Processing


Zoom in and drag
The Bitmap object is dragged on The View Based on Single-touch, and the View edge is detected to prevent the drag from passing through the border. The Bitmap object is amplified on The View Based on Two-point touch, and the magnification is detected. Bitmap can be scaled up and translated on a View based on a Matrix object. A Matrix object is a Matrix used in android to implement geometric transformation of images. It supports common operations such as translation, amplification, reduction, miscutting, and rotation.

Update and display of Bitmap objects in View
By reloading the onDraw method, you can use canvas to draw Bitmap objects and use the view. invalidate () method to refresh views.

Description of important methods of the MyImageView class:
InitParameters () initializes all required parameters
SetStartPoint () sets the coordinates of the start point of image translation.

SetMovePoint () is used to set the coordinates of the moving points of the image translation, and then calculate the distance between the start points of the set to obtain the two parameter values sx and sy to be translated by the Bitmap object. This also includes the check code that ensures that the image does not cross the View boundary.

SavePreviousResult () saves the current Translation Data. Next time, you can continue to translate Bitmap Objects Based on the next translation.

ZoomIn () scales up the Bitmap on the View object based on the Euclidean distance between the two points through initial distance comparison.

 

Matrix APIs for amplification and Translation

The Matrix. postScale method and the Matrix. postTranslate method can achieve translation and amplification without changing the Bitmap object itself.

 

Ii. Code Implementation

The custom View class uses the xml layout as follows:

 

     
  
 
The custom View implementation code is as follows:

 

 

Package com. example. matrixdemo; import android. content. context; import android. graphics. bitmap; import android. graphics. canvas; import android. graphics. color; import android. graphics. matrix; import android. graphics. paint; import android. graphics. paint. style; import android. graphics. point; import android. graphics. rect; import android. util. attributeSet; import android. view. view; public class MyImageView extends View {private Paint mPaint; private Bitmap bitmap; private Matrix matrix; // Translation Start Point and Moving Point private Point startPoint; private Point movePoint; private float initDistance; // record the current translation distance: private int sx; private int sy; // Save the translation status: private int oldsx; private int oldsy; // scale rateprivate float widthRate; private float heightRate; public MyImageView (Context context) {super (context);} public MyImageView (Context context, Attr IbuteSet attrs) {super (context, attrs);} public void setBitmap (Bitmap bitmap) {this. bitmap = bitmap;} private void initParameters () {// initialize the Paint brush mPaint = new Paint (); mPaint. setColor (Color. BLACK); matrix = new Matrix (); if (bitmap! = Null) {float iw = bitmap. getWidth (); float ih = bitmap. getHeight (); float width = this. getWidth (); float height = this. getHeight (); // initial shrinkage ratio widthRate = width/iw; heightRate = height/ih;} sx = 0; sy = 0; oldsx = 0; oldsy = 0 ;} public void setStartPoint (Point startPoint) {this. startPoint = startPoint;} public void setInitDistance (float initDistance) {this. initDistance = initDistance;} public void zoomIn (fl Oat distance) {float rate = distance/this. initDistance; float iw = bitmap. getWidth (); float ih = bitmap. getHeight (); float width = this. getWidth (); float height = this. getHeight (); // get scale ratewidthRate = (width/iw) * rate; heightRate = (height/ih) * rate; // make it same as view sizefloat iwr = (width/iw); float ihr = (height/ih); if (iwr> = widthRate) {widthRate = (width/iw);} if (ihr> = h EightRate) {heightRate = (height/ih);} // go to centeroldsx = (int) (width-widthRate * iw)/2); oldsy = (int) (height-heightRate * ih)/2);} public void setMovePoint (Point movePoint) {this. movePoint = movePoint; sx = this. movePoint. x-this. startPoint. x; sy = this. movePoint. y-this. startPoint. y; float iw = bitmap. getWidth (); float ih = bitmap. getHeight (); // Edge Detection int deltax = (int) (widthRate * iw) -This. getWidth (); int deltay = (int) (heightRate * ih)-this. getHeight (); if (sx + this. oldsx)> = 0) {this. oldsx = 0; sx = 0;} else if (sx + this. oldsx) <=-deltax) {this. oldsx =-deltax; sx = 0;} if (sy + this. oldsy)> = 0) {this. oldsy = 0; this. sy = 0;} else if (sy + this. oldsy) <=-deltay) {this. oldsy =-deltay; this. sy = 0;} float width = this. getWidth (); // initial shrinkage ratio float iwr = width/iw; if (iwr = widthRa Te) {sx = 0; sy = 0; oldsx = 0; oldsy = 0 ;}} public void savePreviousResult () {this. oldsx = this. sx + this. oldsx; this. oldsy = this. sy + this. oldsy; // zerosx = 0; sy = 0 ;}@ Overrideprotected void onDraw (Canvas canvas) {if (matrix = null) {initParameters ();} if (bitmap! = Null) {matrix. reset (); matrix. postScale (widthRate, heightRate); matrix. postTranslate (oldsx + sx, oldsy + sy); canvas. drawBitmap (bitmap, matrix, mPaint);} else {// fill rectRect rect = new Rect (0, 0, getWidth (), getHeight (); mPaint. setAntiAlias (true); mPaint. setColor (Color. BLACK); mPaint. setStyle (Style. FILL_AND_STROKE); canvas. drawRect (rect, mPaint );}}}
The code for listening to OnTouchListener and processing MotionEvent events of a View in the Activity class is as follows:

 

 

package com.example.matrixdemo;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Point;import android.os.Bundle;import android.util.Log;import android.view.Menu;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;public class MainActivity extends Activity implements OnTouchListener {public static final int SCALE_MODE = 4;public static final int TRANSLATION_MODE = 2;public static final int NULL_MODE = 1;private MyImageView myView;private int mode;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);startMyImageView();}private void startMyImageView() {myView = (MyImageView) this.findViewById(R.id.myView);Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(),R.drawable.flower_001);myView.setBitmap(bitmap);myView.setOnTouchListener(this);myView.invalidate();}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic boolean onTouch(View view, MotionEvent event) {Log.i(touch event,touch x =  + event.getX());switch (MotionEvent.ACTION_MASK & event.getAction()) {case MotionEvent.ACTION_DOWN:mode = TRANSLATION_MODE;myView.setStartPoint(new Point((int)event.getX(), (int)event.getY()));break;case MotionEvent.ACTION_POINTER_UP:case MotionEvent.ACTION_OUTSIDE:case MotionEvent.ACTION_UP:mode = NULL_MODE;myView.savePreviousResult();break;case MotionEvent.ACTION_POINTER_DOWN:mode = SCALE_MODE;myView.setInitDistance(calculateDistance(event));break;case MotionEvent.ACTION_MOVE:if(mode == SCALE_MODE){float dis = calculateDistance(event);myView.zoomIn(dis);}else if(mode == TRANSLATION_MODE){myView.setMovePoint(new Point((int)event.getX(), (int)event.getY()));}else{Log.i(unknow mode tag,do nothing......);}break;}myView.invalidate();return true;}private float calculateDistance(MotionEvent event) {float dx = event.getX(0) - event.getX(1);float dy = event.getY(0)  - event.getY(1);float distance = (float)Math.sqrt(dx*dx + dy*dy);return distance;}}
Iii. Running effect:

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.