Let's look at a very simple core image scaling method:
public static Bitmap scale (Bitmap Bitmap, float scalewidth, float scaleheight) {
int width = bitmap.getwidth ();
int height = bitmap.getheight ();
Matrix matrix = new Matrix ();
Matrix.postscale (ScaleWidth, scaleheight);
LOG.I (TAG, "ScaleWidth:" + ScaleWidth + ", ScaleHeight:" + scaleheight);
Return Bitmap.createbitmap (Bitmap, 0, 0, width, height, matrix, True);
}
Note that if you want to scale correctly, you may overflow memory, such as when you used picture scaling:
Java.lang.IllegalArgumentException:bitmap size exceeds 32bits
Later a line of code, found that the original is the proportion of scale calculation error, will be magnified to 20 times, resulting in memory overflow, modified proportional value after the normal.
Okay, so here's a real look at this module that enables zooming and scaling up to two levels in the original size.
Features are:
- Zoom in at the center of the touch point (this is not on the other code on the Web)
- Border control (this is not the other code on the Web)
- Double-click to enlarge or shrink (mainly for resistive screen)
- Multi-point Touch zoom and zoom Out
This module has passed the test, and the user has been used for some time, it is more stable.
The following code and use methods (no write test project, everyone forgive):
ImageControl is similar to a user-defined ImageView control. The usage is posted in the following code.
Import Android.content.Context;
Import Android.graphics.Bitmap;
Import Android.graphics.Matrix;
Import Android.util.AttributeSet;
Import Android.util.FloatMath;
Import android.view.MotionEvent;
Import Android.widget.ImageView;
public class ImageControl extends ImageView {public ImageControl (context) {super); TODO auto-generated Constructor stub} public ImageControl (context context, AttributeSet Attrs) {Super (CO
ntext, attrs);
TODO auto-generated Constructor stub} public ImageControl (context, AttributeSet attrs, int defstyle) {
Super (context, attrs, Defstyle);
TODO auto-generated Constructor stub}//ImageView img; Matrix Imgmatrix = null; Define the transformation matrix of the picture static final int double_click_time_space = 300; Double-click interval static final int double_point_distance = 10;
Two point amplification two points between minimum spacing static final int NONE = 0; static final int DRAG = 1; Drag operation static final int ZOOM = 2; Zoom in, zoom in.as private int mode = NONE; Current mode float Bigscale = 3f; Default magnification Boolean Isbig = false; Is the magnification state long lastclicktime = 0; Click Time float startdistance; Multi-point Touch two point distance float enddistance; Multi-point Touch two point distance float topheight;
Status bar height and title bar height Bitmap primarybitmap = null; float CONTENTW; Screen content area width float contenth; The screen content area height float primaryw; Original artwork width float primaryh; Original height float scale; Suitable for screen scaling multiple Boolean Ismovex = true; Allow Boolean Ismovey = True to be dragged on the x axis;
Whether to allow the float startx to be dragged on the Y axis;
float Starty;
float EndX;
float EndY;
float SUBX;
float Suby;
float limitX1;
float limitX2;
float limitY1;
float limitY2;
Icustommethod mcustommethod = null;
/** * Initialization Picture * * @param bitmap * To display the picture * @param contentw * Content Area width * @param contenth * Content Area Height * @param topheight * status bar height and title bar height and/public void Imageinit (Bitmap Bitmap, int conte NTW, int contenth, int topHeight, Icustommethod icustommethod) {this.primarybitmap = bitmap;
THIS.CONTENTW = CONTENTW;
This.contenth = Contenth;
This.topheight = Topheight;
Mcustommethod = Icustommethod;
Primaryw = Primarybitmap.getwidth ();
Primaryh = Primarybitmap.getheight ();
float ScaleX = (float) contentw/primaryw;
float ScaleY = (float) contenth/primaryh; Scale = ScaleX < ScaleY?
Scalex:scaley;
if (Scale < 1 && 1/scale < Bigscale) {Bigscale = (float) (1/scale + 0.5);
} Imgmatrix = new Matrix ();
SUBX = (CONTENTW-PRIMARYW * scale)/2;
Suby = (CONTENTH-PRIMARYH * scale)/2;
This.setimagebitmap (PRIMARYBITMAP);
This.setscaletype (Scaletype.matrix);
Imgmatrix.postscale (scale, scale);
Imgmatrix.posttranslate (SUBX, Suby);
This.setimagematrix (Imgmatrix); /** * Press Operation * @param event/public void MouseDown (Motionevent event) {mode = NONE;
StartX = Event.getrawx ();
Starty = Event.getrawy (); if (event.getpointercount () = = 1) {//If two clicks interval is less than a certain value, the default is to double-click event if (Event.geteventtime ()-Lastclicktime ;
Double_click_time_space) {changesize (startx, starty);
else if (isbig) {mode = DRAG;
} lastclicktime = Event.geteventtime (); /** * Not the first click Operation * * @param event/public void Mousepointdown (Motionevent event) {STARTDI
Stance = Getdistance (event);
if (Startdistance > double_point_distance) {mode = ZOOM;
else {mode = NONE; }/** * Move operation * * @param event/public void MouseMove (Motionevent event) {if (mode = =
DRAG) && (Ismovex | | | ismovey)) {float[] XY = gettranslatexy (Imgmatrix);
float TRANSX = 0;
float Transy = 0;
if (Ismovex) {endx = Event.getrawx ();
TRANSX = Endx-startx; if ((xy[0)+ transx) <= limitX1) {transx = limitx1-xy[0];
} if ((xy[0) + transx) >= limitX2) {transx = limitx2-xy[0];
} if (Ismovey) {EndY = Event.getrawy ();
Transy = Endy-starty;
if ((Xy[1] + transy) <= limitY1) {transy = limity1-xy[1];
} if ((xy[1) + transy) >= limitY2) {transy = limity2-xy[1];
} imgmatrix.posttranslate (TRANSX, Transy);
StartX = EndX;
Starty = EndY;
This.setimagematrix (Imgmatrix);
else if (mode = = ZOOM && event.getpointercount () > 1) {enddistance = Getdistance (event);
float dif = enddistance-startdistance;
if (Math.Abs (enddistance-startdistance) > Double_point_distance) {if (Isbig) {if (dif < 0) {
Changesize (0, 0);
mode = NONE;
} else if (dif > 0) { float x = event.getx (0)/2 + EVENT.GETX (1)/2;
Float y = event.gety (0)/2 + event.gety (1)/2;
Changesize (x, y);
mode = NONE;
/** * Mouse Lift Event/public void MouseUp () {mode = NONE; /** * Image Zoom Zoom Out * * @param x * Click point x Coordinate * @param y * Click Point y-coordinate/private void Cha
Ngesize (float x, float y) {if (Isbig) {//If in Maximum state, restore Imgmatrix.reset ();
Imgmatrix.postscale (scale, scale);
Imgmatrix.posttranslate (SUBX, Suby);
Isbig = false;
else {Imgmatrix.postscale (Bigscale, Bigscale);///////////////((bigScale-1) * x); float Transy =-((bigScale-1) * (y-topheight));
(bigScale-1) (Y-statusbarheight-suby) +2*suby; float currentwidth = primaryw * scale * bigscale;
Enlarged picture size Float Currentheight = primaryh * scale * bigscale; If the picture is enlarged and exceeds the screen range process if (CurreNtheight > Contenth) {limitY1 =-(Currentheight-contenth);//translation restriction limitY2 = 0; Ismovey = true; Allows you to drag a float Currentsuby = Bigscale * Suby on the y axis;
After the current translation distance//translation, the upper part of the content area has a blank handling method if (-transy < Currentsuby) {transy =-currentsuby; if (Currentsuby + Transy < limitY1) {Transy =-(Currentheight +), the lower part of the content area has a blank processing method after translation.
Currentsuby-contenth);
} else {//If the picture does not exceed the screen scope after zooming in, drag Ismovey = False is not allowed;
} if (Currentwidth > contentw) {limitX1 =-(CURRENTWIDTH-CONTENTW);
limitX2 = 0;
Ismovex = true;
float CURRENTSUBX = Bigscale * SUBX;
if (-transx < CURRENTSUBX) {transx =-CURRENTSUBX;
} if (CURRENTSUBX + TRANSX < limitX1) {TRANSX =-(currentwidth + CURRENTSUBX-CONTENTW);
} else {Ismovex = false;
}
Imgmatrix.posttranslate (TRANSX, Transy);
Isbig = true;
} this.setimagematrix (Imgmatrix);
if (Mcustommethod!= null) {Mcustommethod.custommethod (isbig); }/** * Gets the x-axis offset and y-axis offset of the transformation matrix * * @param matrix * Transformation matrices * @return/private float[]
Gettranslatexy (Matrix matrix) {float[] values = new float[9];
Matrix.getvalues (values);
float[] floats = new float[2];
Floats[0] = values[matrix.mtrans_x];
FLOATS[1] = values[matrix.mtrans_y];
return floats;
/** * Get the distance between two points * * @param event * @return/Private float Getdistance (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); /** * @author Administrator User-defined method */public interface Icustommethod {public void Custommethod (Bo
Olean currentstatus);
}
}
Imagevewactivity This activity for testing
Import android.app.Activity;
Import Android.graphics.Bitmap;
Import Android.graphics.Rect;
Import android.graphics.drawable.BitmapDrawable;
Import Android.os.Bundle;
Import android.view.MotionEvent;
Import Android.view.View;
Import Android.widget.LinearLayout;
Import Android.widget.TextView;
Import Android.widget.Toast;
Import Ejiang.boiler.ImageControl.ICustomMethod;
Import ejiang.boiler.r.id;
public class Imageviewactivity extends activity {@Override protected void onCreate (Bundle savedinstancestate) {
TODO auto-generated Method Stub super.oncreate (savedinstancestate);
Setcontentview (R.layout.common_image_view);
Findview ();
} public void Onwindowfocuschanged (Boolean hasfocus) {super.onwindowfocuschanged (hasfocus);
Init ();
} ImageControl Imgcontrol;
LinearLayout Lltitle;
TextView Tvtitle;
private void Findview () {Imgcontrol = (ImageControl) Findviewbyid (id.common_imageview_imagecontrol1); LLtitle = (linearlayout) Findviewbyid (id.common_imageview_lltitle);
Tvtitle = (TextView) Findviewbyid (id.common_imageview_title);
private void Init () {tvtitle.settext ("Picture test");
This can be dynamically assigned to the picture path of the Imgcontrol/...
Bitmap bmp;
if (Imgcontrol.getdrawingcache ()!= null) {BMP = Bitmap.createbitmap (Imgcontrol.getdrawingcache ());
else {bmp = ((bitmapdrawable) imgcontrol.getdrawable ()). Getbitmap ();
} Rect frame = new Rect ();
GetWindow (). Getdecorview (). Getwindowvisibledisplayframe (frame);
int statusbarheight = Frame.top;
int screenw = This.getwindowmanager (). Getdefaultdisplay (). GetWidth ();
int screenh = This.getwindowmanager (). Getdefaultdisplay (). GetHeight ()-statusbarheight;
if (BMP!= null) {imgcontrol.imageinit (BMP, Screenw, Screenh, Statusbarheight, New Icustommethod () { @Override public void Custommethod (Boolean cUrrentstatus) {//////When the picture is zoomed in or out, control whether the caption displays if (currentstatus) {Lltitle.setv
Isibility (View.gone);
else {lltitle.setvisibility (view.visible);
}
}
}); else {toast.maketext (imageviewactivity.this, "Picture load failed, please try again later!")
", Toast.length_short). Show (); @Override public boolean ontouchevent (Motionevent event) {switch (Event.getaction () & Motioneve Nt.
Action_mask) {case MotionEvent.ACTION_DOWN:imgControl.mouseDown (event);
Break
/** * Not the first point press/Case MotionEvent.ACTION_POINTER_DOWN:imgControl.mousePointDown (event);
Break
Case MotionEvent.ACTION_MOVE:imgControl.mouseMove (event);
Break
Case MotionEvent.ACTION_UP:imgControl.mouseUp ();
Break Return Super.ontouchevent (Event);
}
}
In the code above, you need to be aware of two points. In an activity, the Ontouchevent method is overridden to pass a touch event to ImageControl, similar to the routed event mechanism in WPF. The second initialization Imgcontrol is the Imgcontrol.imageinit, which takes note of the parameters. The last parameter is similar to a delegate in C #, which I use to implement, and unload this method when I zoom in on a narrowing switch.
Common_image_view.xml Layout file
<?xml version= "1.0" encoding= "Utf-8"?> <relativelayout "xmlns:android=" /schemas.android.com/apk/res/android "android:id=" @+id/rl "android:layout_width=" Fill_parent "Android:layout_heig" ht= "Fill_parent" > <ejiang.boiler.imagecontrol android:id= "@+id/common_imageview_imagecontrol1" Andro
Id:layout_width= "Fill_parent" android:layout_height= "fill_parent" android:src= "@drawable/ic_launcher"/> <linearlayout android:id= "@+id/common_imageview_lltitle" style= "@style/reporttitle1" Android:layout_ali Gnparentleft= "true" android:layout_alignparenttop= "true" > <textview android:id= "@+id/common_imag" Eview_title "style=" @style/title2 "android:layout_width=" fill_parent "android:layout_height=" Wrap_con
Tent "android:layout_weight=" 1 "android:text=" Report "/> </LinearLayout> </RelativeLayout>