Android image viewing supports double-click zoom-in and multi-point touch

Source: Internet
Author: User
Tags gety

I wrote it some time ago and I will share it for your reference.

I have studied the source code of the image library, but it is too complicated for me to understand! I have also referred to some source code on the Internet, but many functions are incomplete. They are not what I want! I wrote a Class Based on the online code and some source code of the Image Library.

Unimplemented functions-step-by-step amplification, this matrix transformation will make me dizzy, and the project will not be used, so I will not study it any more.

This module mainly achieves two levels of zoom-in and original size scaling.

Features:

  1. Zoom in with the touch point as the center (this is not available in other code on the Internet)
  2. Border control (this is not available in other code on the Internet)
  3. Double-click zoom in or out (mainly considering the resistance screen)
  4. Multi-touch zoom-in and zoom-out

This module has passed the test and the user has been using it for a while. It is relatively stable.

Below is the code and usage (no test project is written. Sorry ):

Imagecontrol. CS is similar to a custom imageview control. The usage will be 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 (context); // todo auto-generated constructor stub} public imagecontrol (context, attrib Uteset attrs) {super (context, 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 image static final int double_click_time_space = 300; // double-click the time interval static final int double_point_distance = 10; // The minimum gap between two points to enlarge static fi NAL int none = 0; static final int drag = 1; // drag the static final int zoom = 2; // zoom in or out the private int mode = none; // float bigscale = 3f in the current mode; // default magnification: Boolean isbig = false; // whether the zoom-in status is long lastclicktime = 0; // click the float startdistance; // two-point touch distance from float enddistance; // two-point touch distance from float topheight; // bitmap primarybitmap = NULL; float contentw; // float contenth; // float primaryw; // Float primaryh; // float scale of the source image height; // Boolean ismovex = true; // specifies whether to allow Boolean ismovey = true to be dragged on the X axis; // whether float startx; float starty; float endx; float Endy; float subx; float Suby; float limitx1; float limitx2; float limity1; float limity2; icustow.hod mcustow.hod = NULL; /***** initialize the image ** @ Param bitmap * the image to be displayed * @ Param contentw * content area width * @ Param contenth * content area height * @ Param topheight * Sum of the Status Bar Height and title bar height */Public void imageinit (Bitmap bitmap, int contentw, int contenth, int topheight, icustow.hod) {This. primarybitmap = bitmap; this. contentw = contentw; this. contenth = contenth; this. topheight = topheight; mcustow.hod = icustow.hod; 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);}/***** click ** @ Param even T */Public void mousedown (motionevent event) {mode = none; startx = event. getrawx (); starty = event. getrawy (); If (event. getpointercount () = 1) {// If the interval between two clicks is less than a certain value, double-click event if (event. geteventtime ()-lastclicktime <double_click_time_space) {changesize (startx, starty);} else if (isbig) {mode = drag ;}} lastclicktime = event. geteventtime ();}/*** click ** @ Param event */Public void mousepointdown (M Otionevent) {startdistance = 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] + Trans X) <= 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 ;} /*** zoom in and out the image ** @ Param x * click the X coordinate * @ Param y * click the Y coordinate */private void changesize (float X, float y) {If (isbig) {// restore imgmatrix if it is in the maximum state. reset (); imgmatrix. postscale (scale, scale); imgmatrix. posttranslate (subx, Suby); isbig = false;} else {imgmatrix. postscale (bigscale, bigscale); // after the original matrix, multiply the float transx =-(bigscale-1) * X); float transy =-(bigscale-1) * (Y-topheight); // (bigScale-1) (Y-statusbarheight-Suby) + 2 * Suby; float currentwidth = primaryw * scale * bigscale; // float currentheight = primaryh * scale * bigscale; // if the image is enlarged beyond the screen range and processed if (currentheight> contenth) {limity1 =-(currentheight-contenth); // limit of translation limity2 = 0; ismovey = true; // float currentsuby = bigscale * Suby can be dragged on the Y axis; // The current translation distance // After the translation, there is a blank upper part of the content area. Solution: If (-transy <currentsub Y) {transy =-currentsuby;} // after translation, there is a blank solution in the lower part of the content area if (currentsuby + transy <limity1) {transy =-(currentheight + currentsuby-contenth) ;}} else {// if the image is not scaled up beyond the screen range, drag ismovey = false ;} if (currentwidth> contentw) {limitx1 =-(currentwidth-contentw); limitx2 = 0; ismovex = true; float currentsubx = bigscale * subx; If (-transx <currentsubx) {transx =-currentsubx;} If (currentsubx + transx <Limi Tx1) {transx =-(currentwidth + currentsubx-contentw) ;}} else {ismovex = false;} imgmatrix. posttranslate (transx, transy); isbig = true;} This. setimagematrix (imgmatrix); If (mcustow.hod! = NULL) {mcustow.hod. custommethod (isbig );}} /*** get the X-axis offset and Y-axis offset in the transformation matrix *** @ Param matrix * @ return */private float [] gettranslatexy (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 (Boolean currentstatus );}}

 

Imagevewactivity. CS: activity used 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. icustow.hod; import ejiang. boiler. r. ID; public class im Ageviewactivity extends activity {@ overrideprotected void oncreate (bundle savedinstancestate) {// todo auto-generated method stubsuper. 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 ("image test"); // You can dynamically assign a value to the image path of 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 (). getdefadisplay display (). getwidth (); int screenh = This. getwindowmanager (). getdefadisplay display (). getheight ()-Status Barheight; If (BMP! = NULL) {imgcontrol. imageinit (BMP, screenw, screenh, statusbarheight, new icustow.hod () {@ overridepublic void custommethod (Boolean currentstatus) {// when the image is in the zoom-in or zoom-out status, controls whether the title displays if (currentstatus) {lltitle. setvisibility (view. gone);} else {lltitle. setvisibility (view. visible) ;}}) ;}else {toast. maketext (imageviewactivity. this, "image loading failed. Please try again later! ", Toast. length_short ). show () ;}@ overridepublic Boolean ontouchevent (motionevent event) {Switch (event. getaction () & motionevent. action_mask) {Case motionevent. action_down: imgcontrol. mousedown (event); break;/*** press not the first vertex */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 above Code, pay attention to two points. In an activity, override the ontouchevent method and pass the touch event to imagecontrol. This is similar to the routing event mechanism in WPF. Second, initialize imgcontrol, that is, imgcontrol. imageinit. Pay attention to the parameters. The last parameter is similar to the delegate in C #. Here I use the interface to implement it. The operations to be executed during the zoom-in and zoom-out switching are all uninstalled in this method.

Common_image_view.xml layout File

<? XML version = "1.0" encoding = "UTF-8"?> <Relativelayout xmlns: Android = "http://schemas.android.com/apk/res/android" Android: Id = "@ + ID/RL" Android: layout_width = "fill_parent" Android: layout_height = "fill_parent"> <ejiang. boiler. imagecontrol Android: Id = "@ + ID/common_imageview_imagecontrol1" Android: 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_alignparentleft = "true" Android: layout_alignparenttop = "true"> <textview Android: Id = "@ + ID/common_imageview_title" style = "@ style/title2" Android: layout_width = "fill_parent" Android: layout_height = "wrap_content" Android: layout_weight = "1" Android: text = "report"/> </linearlayout> </relativelayout>

I haven't been learning Android for a long time, so there are some mistakes or errors. You are welcome to point them out!

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.