As a result of the project's requirements, we have been studying the scalability ImageView recently, using this article to document what has been learned recently:
The implementation features of the ImageView are:
1) When initially opened, the picture is displayed proportionally fullscreen (fill ImageView).
2) in the zoom in and out process, you can control the maximum magnification and the minimum reduction ratio.
3) in the zoom process, if the width or height of the picture is less than ImageView, the picture is displayed in a wide or high center.
4) After zooming in, you can move the picture, and limit the movement of the border, not beyond the picture.
5) Double-click to enlarge or zoom out the function. (If the current picture is displayed as the largest scale then the minimum scale is reduced, but the maximum scale is magnified if the minimum scale is not)
Before you speak the code, you should first talk about a class, Matrix. Because we are in the process of processing pictures, we need to shift the image, zoom, and so on, and the matrix is just to help us encapsulate the data, specifically, you can look at this article: Android from the Matrix to get processed pictures of the actual width of the focus is to understand the matrix inside the meaning of the array.
Code, the specific description of the code are described in one:
Myzoomimageview.java file:
Package Com.xiaoyan.doubletouch;import Android.content.context;import Android.graphics.matrix;import Android.graphics.pointf;import Android.graphics.drawable.drawable;import Android.util.attributeset;import Android.util.floatmath;import Android.view.motionevent;import Android.view.view;import Android.view.viewtreeobserver;import Android.view.viewtreeobserver.ongloballayoutlistener;import android.widget.imageview;/** * Zoom ImageView * * @author Xiejinxiong * */public class Myzoomimageview extends ImageView {/ * * ImageView height */private int imgheight;/** imageview width */private int imgwidth;/** picture height */private int intrinsicheight;/** diagram Slice width */private int intrinsicwidth;/** max zoom level */private float Mmaxscale = 2.0f;/** minimum zoom level */private float Mminscale = 0.2f;/ * * Used to record the coordinate position of the dragged picture movement */private Matrix matrix = new Matrix ();/** is used to record the coordinates where the picture is to be dragged */private Matrix Currentmatrix = new Matr IX ();/** records the time of first click */private long firsttouchtime = 0;/** time click interval */private int intervaltime = 250;/** First point finish coordinates */privatePointF Firstpointf;public Myzoomimageview (context context) {super (context); Initui ();} Public Myzoomimageview (context context, AttributeSet Attrs) {Super (context, attrs); Initui ();} Public Myzoomimageview (context context, AttributeSet attrs, int defstyle) {Super (context, attrs, defstyle);//TODO Auto-g Enerated constructor Stubinitui ();} /** * Initialize UI */private void Initui () {this.setscaletype (scaletype.fit_center); This.setontouchlistener (new Touchlistener ()); Getimageviewwidthheight (); Getintrinsicwidthheight ();} /** * Get the picture intrinsic width high */private void Getintrinsicwidthheight () {drawable drawable = this.getdrawable ();// Initialize the width of the bitmap intrinsicheight = Drawable.getintrinsicheight (); intrinsicwidth = Drawable.getintrinsicwidth ();} Private Final class Touchlistener implements Ontouchlistener {/** record is drag-and-zoom mode */private int mode = 0;//Initial state/** drag Photo mode */private static final int mode_drag = 1;/** Zoom out photo mode */private static final int mode_zoom = 2;/** used to record the coordinates at the beginning of the position */PR Ivate PointF startPoint = new PointF ();/** Two finger start distance */private float startdis;/** Two finger mid point */private PointF midpoint;public boolean onTouch (View V, motionevent Eve NT) {/** last eight bits motionevent.action_mask = 255 */switch (event.getaction () & Motionevent.action_mask) {//single-point listening and multipoint Touch Monitor//finger press down screen case MotionEvent.ACTION_DOWN:mode = mode_drag;//record ImageView current move position currentmatrix.set (Getimagematrix ()) ; Startpoint.set (Event.getx (), event.gety ()); Matrix.set (Currentmatrix); Makeimageviewfit (); break;//finger moves on the screen, The event will be constantly triggered case motionevent.action_move://drag picture if (mode = = Mode_drag) {//System.out.println ("Action_move_____mode_drag "); float dx = Event.getx ()-startpoint.x; Get the moving distance of the x-axis float dy = event.gety ()-startpoint.y; Get the X-axis movement distance//move zmatrix.set (Currentmatrix) in position before moving it; float[] values = new Float[9];matrix.getvalues (values);d x = Checkdxbound (values, dx);d y = checkdybound (values, dy); matrix.posttranslate (dx, dy);} Zoom in and out of the picture else if (mode = = Mode_zoom) {Float Enddis = distance (event);//End Distance if (Enddis > 10f) {//two fingers together, pixels greater than 10fLoat scale = enddis/startdis;//Gets the zoom multiplier matrix.set (Currentmatrix); float[] values = new Float[9];matrix.getvalues (values) ; scale = Checkfitscale (scale, values); Matrix.postscale (scale, scale, midpoint.x, MIDPOINT.Y);}} break;//Finger off Screen case MotionEvent.ACTION_UP:setDoubleTouchEvent (event); case motionevent.action_pointer_up:// System.out.println ("action_pointer_up"); mode = 0;//Matrix.set (Currentmatrix); float[] values = new float[9]; Matrix.getvalues (values); break;//when there is already a contact (finger) on the screen, and then a touch point presses down on the screen case Motionevent.action_pointer_ down://System.out.println ("Action_pointer_down"); mode = mode_zoom;/** calculates the distance between two fingers */startdis = distance (event);/** Calculates the middle point between two fingers */if (Startdis > 10f) {//two fingers close together when the pixel is greater than 10midPoint = Mid (event);//Record the current ImageView zoom multiplier Currentmatrix.set (Getimagematrix ());} break;} Setimagematrix (matrix); return true;} /** calculates the distance between two fingers */private float distance (motionevent event) {Float dx = event.getx (1)-event.getx (0); float dy = event.gety (1)-event.gety (0)/** use the Pythagorean theorem to return the distance between two pointsFrom */return floatmath.sqrt (DX * dx + dy * dy);} /** calculates the middle point between two fingers */private PointF mid (Motionevent event) {Float Midx = (event.getx (1) + event.getx (0))/2;float Midy = (ev Ent.gety (1) + event.gety (0)/2;return new PointF (Midx, midy);} /** * and current matrix comparison, test dy, so that the image will not be moved beyond the imageview boundary * * @param values * @param dy * @return */private float checkdybound (float[] Val UEs, float dy) {Float height = imgheight;if (intrinsicheight * values[matrix.mscale_y] < height) return 0;if (Values[mat Rix. Mtrans_y] + dy > 0) dy =-values[matrix.mtrans_y];else if (values[matrix.mtrans_y] + dy <-(intrinsicheight* Values[M Atrix. Mscale_y]-height)) dy =-(Intrinsicheight * values[matrix.mscale_y]-height)-Values[matrix.mtrans_y];return dy; /** * Compared to the current matrix, verify DX so that the image moves beyond the imageview boundary * * @param values * @param dx * @return */private float checkdxbound (float[] Val UEs, float dx) {Float width = imgwidth;if (intrinsicwidth * values[matrix.mscale_x] < width) return 0;if (Values[matrix. MTRANS_X] + dx > 0) dx =-valueS[matrix.mtrans_x];else if (values[matrix.mtrans_x] + dx <-(intrinsicwidth* values[matrix.mscale_x]-width)) dx =-(i Ntrinsicwidth * values[matrix.mscale_x]-width)-Values[matrix.mtrans_x];return dx;} /** * Mscale is used to process the zoom transform * * * Mskew to handle the wrong tangent transform * * * Mtrans used to process the translation transformation *//** * Test scale so that the image is scaled without exceeding the maximum multiples * * @param scales * @para M values * @return */private float Checkfitscale (float scale, float[] values) {if (scale * values[matrix.mscale_x] > MM Axscale) scale = mmaxscale/values[matrix.mscale_x];if (scale * values[matrix.mscale_x] < Mminscale) scale = Mminscale/ Values[matrix.mscale_x];return scale;} /** * cause the picture to be centered * * @param values * (contains picture change information) */private void Makeimgcenter (float[] values) {//zoom the picture's height float zo omy = intrinsicheight * Values[matrix.mscale_y];float zoomx = intrinsicwidth * values[matrix.mscale_x];//picture upper left corner Y-coordinate float l Efty = values[matrix.mtrans_y];//Picture upper left corner X coordinate float leftx = values[matrix.mtrans_x];//picture lower right corner Y coordinate float righty = lefty + zoomy;// Picture lower right corner x-coordinate float rightx =LEFTX + zoomx;//to center the picture vertically if (Zoomy < imgheight) {float MarY = (imgheight-zoomy)/2.0f;matrix.posttranslate (0, MarY- Lefty);} Center the picture Horizontally if (Zoomx < imgwidth) {float MarX = (IMGWIDTH-ZOOMX)/2.0f;matrix.posttranslate (MARX-LEFTX, 0);} Make the picture zoom up and down (that is, when the size of the picture is larger than the size of ImageView, but leave a little space above or below, the picture will be moved to fill the space) if (zoomy >= imgheight) {if (Lefty > 0) {// Judging the picture above left white matrix.posttranslate (0,-lefty);} if (righty < imgheight) {//Judging the picture below leave white matrix.posttranslate (0, imgheight-righty);}} Make the picture zoom left and right leave white if (zoomx >= imgwidth) {if (Leftx > 0) {//Judge Left White Matrix.posttranslate (-LEFTX, 0);} if (Rightx < ImgWidth) {//judge the picture to the right without leaving white matrix.posttranslate (imgwidth-rightx, 0);}}} /** * Get ImageView's wide-height */private void getimageviewwidthheight () {Viewtreeobserver Vto2 = Getviewtreeobserver (); Vto2.addongloballayoutlistener (New Ongloballayoutlistener () {@SuppressWarnings ("deprecation") public void Ongloballayout () {getviewtreeobserver (). Removeglobalonlayoutlistener (this); imgwidth = GetWidth (); imgHeight =GetHeight ();}});} /** * Allows ImageView to start with the most suitable width and height ratio, which is exactly what it looks like */private void Makeimageviewfit () {if (Getscaletype ()! = Scaletype.matrix) { Setscaletype (Scaletype.matrix); Matrix.postscale (1.0f, 1.0f, IMGWIDTH/2, IMGHEIGHT/2);}} /** * Double-click event Trigger * * @param values */private void Setdoubletouchevent (Motionevent event) {float values[] = new Float[9];matri X.getvalues (values);//Store the current time long currenttime = System.currenttimemillis ();//Determine whether the two-click Spacing time matches if (CurrentTime- Firsttouchtime >= intervaltime) {firsttouchtime = currenttime;firstpointf = new PointF (Event.getx (), Event.getY ());} else {//determine if the distance between two clicks is less than 30fif (Math.Abs (Event.getx ()-firstpointf.x) < 30f&& Math.Abs (Event.gety ()- FIRSTPOINTF.Y) < 30f) {//Determine the current scaling ratio to the maximum minimum ratio if (values[matrix.mscale_x] < Mmaxscale) {Matrix.postscale (Mmaxscale/ Values[matrix.mscale_x],mmaxscale/values[matrix.mscale_x], Event.getx (), event.gety ());} else {Matrix.postscale (mminscale/values[matrix.mscale_x],mminscale/values[matrix.mscale_x], evenT.getx (), event.gety ());}}} /** * Set the maximum and minimum zoom ratio of the picture * * @param mmaxscale * @param mminscale */public void setpiczoomheightwidth (float mmaxscale, float Mminscale) {This.mmaxscale = Mmaxscale;this.mminscale = Mminscale;}}XML file:
<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http// Schemas.android.com/tools " android:layout_width=" match_parent " android:layout_height=" Match_parent " tools:context= "com.xiaoyan.doubletouch.MainActivity" > <com.xiaoyan.doubletouch.myzoomimageview android:id= "@+id/imageview" android:layout_width= "fill_parent" android:layout_height= "fill_parent " android:src=" @drawable/A "/></relativelayout>
Specific implementation results:
Initially shown:
Enlarge display:
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
[Android] Scalable ImageView (can zoom out)