Let’s first look at a very simple method of scaling the core image:
public static Bitmap scale(Bitmap bitmap, float scaleWidth, float scaleHeight) { int width = (); int height = (); Matrix matrix = new Matrix(); (scaleWidth, scaleHeight); (TAG, "scaleWidth:"+ scaleWidth +", scaleHeight:"+ scaleHeight); return (bitmap, 0, 0, width, height, matrix, true); }
Note that the scale should be set correctly, otherwise memory may overflow. For example, I encountered this problem when using image scaling:
: bitmap size exceeds 32bits
Later, I looked up the code line by line and found that the scale calculation error was the scale, and the original image was enlarged by more than 20 times, resulting in memory overflow. It was normal after re-modifying the scale value.
Okay, let’s take a look at this module that implements two levels of zooming and original large.
Functions include:
- Zoom in with the touch point as the center (this is not available in other codes on the Internet)
- Boundary control (this is not available in other codes on the Internet)
- Double-click to zoom in or out (mainly consider the resistor screen)
- Multi-touch zoom in and out
This module has passed the test and has been used by users for a while, so it is relatively stable.
The following is the code and usage method (I have not written a test project, please forgive me):
ImageControl is similar to a user-defined ImageView control. The usage will be posted in the following code.
import ; import ; import ; import ; import ; import ; import ; public class ImageControl extends ImageView { public ImageControl(Context context) { super(context); // TODO Auto-generated constructor stub } public ImageControl(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public ImageControl(Context 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 the time interval static final int DOUBLE_POINT_DISTANCE = 10; // Two points enlarge the minimum spacing between two points static final int NONE = 0; static final int DRAG = 1; // Drag operation static final int ZOOM = 2; // Zoom in and out operation private int mode = NONE; // Current mode float bigScale = 3f; // Default magnification Boolean isBig = false; // Is it in a zoomed state long lastClickTime = 0; // Click time float startDistance; // Multi-touch two points distance float endDistance; // Multi-touch two points distance float topHeight; // Status bar height and title bar height Bitmap primaryBitmap = null; float contentW; // Width of the screen content area float contentH; // The height of the screen content area float primaryW; // Original image width float primaryH; // Original image height float scale; // Suitable for screen zoom multiples Boolean isMoveX = true; // Is it allowed to drag on the X-axis Boolean isMoveY = true; // Is it allowed to drag on the Y axis float startX; float startY; float endX; float endY; float subX; float subY; float limitX1; float limitX2; float limitY1; float limitY2; ICustomMethod mCustomMethod = null; /** * Initialize the picture * * @param bitmap * Image to display * @param contentW * Content area width * @param contentH * Content area height * @param topHeight * Sum of status bar height and title bar height */ public void imageInit(Bitmap bitmap, int contentW, int contentH, int topHeight, ICustomMethod iCustomMethod) { = bitmap; = contentW; = contentH; = topHeight; mCustomMethod = iCustomMethod; primaryW = (); primaryH = (); 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; (primaryBitmap); (); (scale, scale); (subX, subY); (imgMatrix); } /** * Press to operate * * @param event */ public void mouseDown(MotionEvent event) { mode = NONE; startX = (); startY = (); if (() == 1) { // If the time interval between two clicks is less than a certain value, the default is the double-click event if (() - lastClickTime < DOUBLE_CLICK_TIME_SPACE) { changeSize(startX, startY); } else if (isBig) { mode = DRAG; } } lastClickTime = (); } /** * Non-first click operation * * @param event */ public void mousePointDown(MotionEvent event) { startDistance = getDistance(event); if (startDistance > DOUBLE_POINT_DISTANCE) { mode = ZOOM; } else { mode = NONE; } } /** * Mobile 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 = (); transX = endX - startX; if ((XY[0] + transX) <= limitX1) { transX = limitX1 - XY[0]; } if ((XY[0] + transX) >= limitX2) { transX = limitX2 - XY[0]; } } if (isMoveY) { endY = (); transY = endY - startY; if ((XY[1] + transY) <= limitY1) { transY = limitY1 - XY[1]; } if ((XY[1] + transY) >= limitY2) { transY = limitY2 - XY[1]; } } (transX, transY); startX = endX; startY = endY; (imgMatrix); } else if (mode == ZOOM && () > 1) { endDistance = getDistance(event); float dif = endDistance - startDistance; if ((endDistance - startDistance) > DOUBLE_POINT_DISTANCE) { if (isBig) { if (dif < 0) { changeSize(0, 0); mode = NONE; } } else if (dif > 0) { float x = (0) / 2 + (1) / 2; float y = (0) / 2 + (1) / 2; changeSize(x, y); mode = NONE; } } } } /** * Mouse lift event */ public void mouseUp() { mode = NONE; } /** * Picture enlarges and zooms in * * @param x * Click on the X coordinate * @param y * Click on the Y coordinate */ private void changeSize(float x, float y) { if (isBig) { // If in maximum state, restore (); (scale, scale); (subX, subY); isBig = false; } else { (bigScale, bigScale); // Multiply the magnification after the original matrix float transX = -((bigScale - 1) * x); float transY = -((bigScale - 1) * (y - topHeight)); // (bigScale-1)(y-statusBarHeight-subY)+2*subY; float currentWidth = primaryW * scale * bigScale; // The image size after enlargement float currentHeight = primaryH * scale * bigScale; // If the image is enlarged and exceeded the screen range, processing if (currentHeight > contentH) { limitY1 = -(currentHeight - contentH); // Pan limit limitY2 = 0; isMoveY = true; // Allow dragging on the Y axis float currentSubY = bigScale * subY; // Current translation distance // After translation, there is a blank solution in the upper part of the content area if (-transY < currentSubY) { transY = -currentSubY; } // After translation, there is a blank solution for the lower part of the content area if (currentSubY + transY < limitY1) { transY = -(currentHeight + currentSubY - contentH); } } else { // If the image is not processed beyond the screen range after enlarging, drag is not allowed isMoveY = false; } 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; } (transX, transY); isBig = true; } (imgMatrix); if (mCustomMethod != null) { (isBig); } } /** * Get the X-axis offset and Y-axis offset in the transformation matrix * * @param matrix * Transform matrix * @return */ private float[] getTranslateXY(Matrix matrix) { float[] values = new float[9]; (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 = (0) - (1); float y = (0) - (1); return (x * x + y * y); } /** * @author Administrator User-defined method */ public interface ICustomMethod { public void customMethod(Boolean currentStatus); } }
ImageVewActivity This Activity for testing
import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; public class ImageViewActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub (savedInstanceState); setContentView(.common_image_view); findView(); } public void onWindowFocusChanged(boolean hasFocus) { (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() { ("Picture Test"); // Here you can dynamically assign values to the image path of imgcontrol // ............ Bitmap bmp; if (() != null) { bmp = (()); } else { bmp = ((BitmapDrawable) ()).getBitmap(); } Rect frame = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); int statusBarHeight = ; int screenW = ().getDefaultDisplay().getWidth(); int screenH = ().getDefaultDisplay().getHeight() - statusBarHeight; if (bmp != null) { (bmp, screenW, screenH, statusBarHeight, new ICustomMethod() { @Override public void customMethod(Boolean currentStatus) { // When the picture is in the zoom-in or out state, control whether the title is displayed if (currentStatus) { (); } else { (); } } }); } else { (, "The picture has failed to load, please try again!", Toast.LENGTH_SHORT) .show(); } } @Override public boolean onTouchEvent(MotionEvent event) { switch (() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: (event); break; /** * Non-first click */ case MotionEvent.ACTION_POINTER_DOWN: (event); break; case MotionEvent.ACTION_MOVE: (event); break; case MotionEvent.ACTION_UP: (); break; } return (event); } }
In the above code, two points need to be paid attention to. In an Activity, you need to override the onTouchEvent method and pass the touch event to the ImageControl, which is similar to the routing event mechanism in WPF. Two initialize imgControl, that is, pay attention to the parameters in it. The last parameter is similar to the delegate in C#. I use the interface to implement it here. All the operations to be performed during the zoom-in switch are uninstalled in this method.
common_image_view.xml Layout file
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:andro android: android:layout_width="fill_parent" android:layout_height="fill_parent" > < android: android:layout_width="fill_parent" android:layout_height="fill_parent" android:src="@drawable/ic_launcher" /> <LinearLayout android: style="@style/reportTitle1" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" > <TextView android: style="@style/title2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="Report" /> </LinearLayout> </RelativeLayout>