Android realizes the ability to enlarge, translate and rotate pictures _android

Source: Internet
Author: User
Tags gety pow touch

Let's take a look at the effect chart that you want to implement

In the explanation, we need to know some knowledge about the principle of picture drawing in advance.

About the process of implementation

1, CustomView

2, to obtain the operation of the pictureBitmap

3, in the method of replication,, View onTouchEvent() ACTION_DOWN ACTION_POINTER_DOWN ACTION_MOVE , ACTION_POINTER_UP and ACTION_UP events.

4, define the corresponding picture change Matrix matrix, through the change of gesture operation to set the corresponding Matrix .

5. Complete the final Matrix setup, redraw the invalidate() page by method.

So next we implement the code step-by-step according to the above process.

Code Demo

/** * Author: zhouyou * Date: 2016/8/23.
  * * public class Touchimageview extends View {//Draw the border of the picture private Paint Paintedge;
  Draw the matrix of the picture in private matrices = new Matrix ();
  The finger presses when the picture's matrix is private matrix Downmatrix = new Matrix ();
  When the finger moves, the picture's matrix is Movematrix = new Matrix ();
  The bitmap of the resource picture private Bitmap srcimage;
  The center point of the multi-touch screen is private PointF midpoint = new PointF ();
  Touch mode private int mode; private static final int NONE = 0; No mode private static final int TRANS = 1; Drag mode private static final int ZOOM = 2;

  Scaling mode//Is over bounds private Boolean withinborder;
  Public Touchimageview {This (context, NULL);
  Public Touchimageview (context, AttributeSet attrs) {This (context, attrs, 0); Touchimageview (context, AttributeSet attrs, int defstyleattr) {Super (context, Attrs, defstyleattr
    );
  Init ();
    private void Init () {Paintedge = new Paint (); Paintedge.setcolor (Color.Black);
    Paintedge.setalpha (170);
  Paintedge.setantialias (TRUE); @Override protected void onsizechanged (int w, int h, int oldw, int oldh) {super.onsizechanged (W, H, OLDW, OLDH
    );
  Srcimage = Bitmapfactory.decoderesource (Getresources (), r.mipmap.ic_avatar_1);
    } @Override protected void OnDraw (Canvas Canvas) {Super.ondraw (Canvas);
    Float[] points = getbitmappoints (srcimage, Matrix);
    float x1 = Points[0];
    float y1 = points[1];
    float x2 = points[2];
    float y2 = points[3];
    Float x3 = points[4];
    float y3 = points[5];
    Float x4 = points[6];
    float y4 = points[7];
    Draw a border Canvas.drawline (x1, y1, x2, y2, Paintedge);
    Canvas.drawline (x2, y2, x4, Y4, Paintedge);
    Canvas.drawline (x4, Y4, X3, Y3, Paintedge);
    Canvas.drawline (x3, Y3, x1, y1, Paintedge);
  Picture Canvas.drawbitmap (srcimage, matrix, NULL);
  ///finger press the X coordinates of the screen private float downx;
  Finger press the y-coordinate of the screen private float DownY; The initial distance between the fingers private float oLddistance;

  The initial angle between the fingers is private float oldrotation;
    @Override public boolean ontouchevent (Motionevent event) {int action = motioneventcompat.getactionmasked (event);
        Switch (action) {case MotionEvent.ACTION_DOWN:mode = TRANS;
        Downx = Event.getx ();
        DownY = Event.gety ();
        Downmatrix.set (matrix);
      Break
        Case Motionevent.action_pointer_down://multi-point touch mode = ZOOM;
        Olddistance = Getspacedistance (event);
        Oldrotation = Getspacerotation (event);
        Downmatrix.set (matrix);
        Midpoint = Getmidpoint (event);
      Break
          Case Motionevent.action_move://Zoom if (mode = = ZOOM) {movematrix.set (Downmatrix);
          float deltarotation = getspacerotation (event)-oldrotation;
          Float scale = getspacedistance (event)/olddistance;
          Movematrix.postscale (scale, scale, midpoint.x, MIDPOINT.Y); Movematrix.postrotate (Deltarotation, Midpoint.x, MIDPOINT.Y);
          Withinborder = Getmatrixbordercheck (Srcimage, Event.getx (), event.gety ());
            if (Withinborder) {matrix.set (Movematrix);
          Invalidate ();
          }//Translate else if (mode = = TRANS) {movematrix.set (Downmatrix);
          Movematrix.posttranslate (Event.getx ()-Downx, Event.gety ()-DownY);
          Withinborder = Getmatrixbordercheck (Srcimage, Event.getx (), event.gety ());
            if (Withinborder) {matrix.set (Movematrix);
          Invalidate ();
      }} break;
        Case MotionEvent.ACTION_POINTER_UP:case MotionEvent.ACTION_UP:mode = NONE;
      Break
    Default:break;
  return true;
    /** * Get the rotation angle of the finger * * @param event * @return/Private float Getspacerotation (Motionevent event) {
    Double deltax = event.getx (0)-event.getx (1);
    Double DeltaY = event.gety (0)-event.gety (1); Double radians =Math.atan2 (DeltaY, deltax);
  return (float) math.todegrees (radians);
    /** * Get the distance between the fingers * * @param event * @return/Private float Getspacedistance (Motionevent event) {
    float x = event.getx (0)-event.getx (1);
    Float y = event.gety (0)-event.gety (1);
  return (float) math.sqrt (x * x + y * y); /** * Get Gesture Center * * @param Event/Private PointF Getmidpoint (Motionevent event) {PointF point = NE
    W PointF ();
    float x = event.getx (0) + event.getx (1);
    Float y = event.gety (0) + event.gety (1);
    Point.set (X/2, Y/2);
  return point;
    /** * Maps the dot of the Matrix to a coordinate point * * @return/protected float[] getbitmappoints (Bitmap Bitmap, matrix matrix) {
    float[] DST = new Float[8]; float[] src = new float[]{0, 0, bitmap.getwidth (), 0, 0, bitmap.getheight (), Bitmap.getwi
    DTH (), Bitmap.getheight ()};
    Matrix.mappoints (DST, SRC);
  return DST; /** * Check Border * * @param x * @param y * @return true-within bounds | false-Beyond boundary/private Boolean Getmatrixbordercheck (Bitmap Bitmap, Floa
    T x, float y) {if (bitmap = null) return false;
    Float[] points = getbitmappoints (bitmap, Movematrix);
    float x1 = Points[0];
    float y1 = points[1];
    float x2 = points[2];
    float y2 = points[3];
    Float x3 = points[4];
    float y3 = points[5];
    Float x4 = points[6];
    float y4 = points[7];
    Float edge = (float) math.sqrt (Math.pow (X1-X2, 2) + Math.pow (Y1-y2, 2)); if ((2 + math.sqrt (2)) * Edge >= math.sqrt (Math.pow (x-x1, 2) + Math.pow (y-y1, 2)) + MATH.SQRT (Math.pow (X- x2, 2) + Math.pow (Y-y2, 2)) + MATH.SQRT (Math.pow (x-x3, 2) + Math.pow (Y-y3, 2)) + MATH.SQRT (Math.pow (
    X-X4, 2) + Math.pow (Y-y4, 2))) {return true;
  return false; }
}

I've already made a detailed comment in my code about the problems that I might encounter.

1. Matrix

  Draw the matrix of the picture in
  private matrices = new Matrix ();
  The finger presses when the picture's matrix is
  private matrix Downmatrix = new Matrix ();
  When the finger moves, the picture's matrix is
  Movematrix = new Matrix ();

First I defined three variables, the purpose of which is to use different gestures to manipulate the image of the Matrix Matrix final by drawing the image Matrix received, so need to be in different operations using different Matrix graphics transformation of the data transfer, so in the rendering of the page will eventually Matrix And then passed back to the drawing Matrix .

2. PointF

  The center point of the multi-touch screen is
  private PointF midpoint = new PointF ();

Because if it's the rotation and magnification of a picture, it needs to be controlled with two fingers, so we need to know the central point coordinates when multiple fingers touch the screen.

3. Touch control mode

  Touch mode
  private int mode;
  private static final int NONE = 0; modeless
  private static final int TRANS = 1;//drag mode
  private static final int ZOOM = 2;//Zoom mode

In the onTouchEvent() event, the touch pattern is transformed according to different events, thus the operation of different image transformations is performed.

4. Ontouchevent ()

First, we are custom View , so if you want to consume the event, you need to set the return value to true .

(1) Action_down-this event is a single touch screen event, which means that if a finger presses the screen, it will recall the event. So we set the touch mode to drag mode (TRANS) in the event, record the XY coordinates of the screen down, and in this event copy the matrix of the drawing to the matrix that presses the screen.

Case Motionevent.action_down:
   mode = TRANS;
   Downx = Event.getx ();
   DownY = Event.gety ();
   Downmatrix.set (matrix);
   Break

(2) Action_pointer_down-This event occurs when more than one finger touches the screen. In this event, we can initialize the settings for the operation of the multi-touch screen. In this event, we reset the touch mode to (ZOOM), initialize the distance between the two fingers touching the screen and the angle of rotation between the two fingers, and initialize the central point coordinates between the two fingers. Finally, the matrix of the drawing is copied to the matrix that presses the screen.

Case Motionevent.action_pointer_down://multi-point touch
    mode = ZOOM;
    Olddistance = Getspacedistance (event);
    Oldrotation = Getspacerotation (event);
    Midpoint = Getmidpoint (event);
    Downmatrix.set (matrix);
    Break

(3) Action_move-to the movement of the event, based on the previous touch mode to determine. First, the matrix that presses the event is copied to the matrix of the mobile event. In the case of the (ZOOM) pattern, we will get the difference between the rotation angle of the finger according to the event and the distance between the fingers. Based on these two differences and the midpoint coordinates obtained in the Action_down event, we can set the zoom and rotation of the move event. The same is true for the (TRANS) model. At last, we can determine whether to render the drawing by obtaining the boundary value of the image transformation.

 case motionevent.action_move://Zoom if (mode = = ZOOM) {Movematrix.set
          (Downmatrix);
          float deltarotation = getspacerotation (event)-oldrotation;
          Float scale = getspacedistance (event)/olddistance;
          Movematrix.postscale (scale, scale, midpoint.x, MIDPOINT.Y);
          Movematrix.postrotate (Deltarotation, Midpoint.x, MIDPOINT.Y);
          Withinborder = Getmatrixbordercheck (Srcimage, Event.getx (), event.gety ());
            if (Withinborder) {matrix.set (Movematrix);
          Invalidate ();
          }//Translate else if (mode = = TRANS) {movematrix.set (Downmatrix);
          Movematrix.posttranslate (Event.getx ()-Downx, Event.gety ()-DownY);
          Withinborder = Getmatrixbordercheck (Srcimage, Event.getx (), event.gety ());
            if (Withinborder) {matrix.set (Movematrix);
          Invalidate (); break; 

(4) Action_pointer_up and ACTION_UP-in both events, the touch screen's mode settings are reset to none.

5. Boundary judgement

The following logic for boundary judgment is for a picture of a square. First, the original image relative to its own four coordinates mapped to the matrix corresponding to the screen point coordinates. By getting the coordinates of the 4 points, we can correlate the coordinates of the picture with the 4 point coordinates of the picture according to the finger's touch.

The logic of the boundary judgment is that the finger touches the picture by the distance of the point to 4 vertices and if the length of the hypotenuse is less than twice times that of the root, it is considered not to exceed the boundary.

/** * Maps Matrix points to coordinate points * * @return/protected float[] getbitmappoints (Bitmap Bitmap, matrix matrix) {
    float[] DST = new Float[8]; float[] src = new float[]{0, 0, bitmap.getwidth (), 0, 0, bitmap.getheight (), Bitmap.getwi
    DTH (), Bitmap.getheight ()};
    Matrix.mappoints (DST, SRC);
  return DST; /** * Check Boundary * * @param x * @param y * @return true-within bounds | false-Beyond boundary/private Boolean Getmatrix
    Bordercheck (Bitmap Bitmap, float x, float y) {if (Bitmap = = null) return false;
    Float[] points = getbitmappoints (bitmap, Movematrix);
    float x1 = Points[0];
    float y1 = points[1];
    float x2 = points[2];
    float y2 = points[3];
    Float x3 = points[4];
    float y3 = points[5];
    Float x4 = points[6];
    float y4 = points[7];
    Float edge = (float) math.sqrt (Math.pow (X1-X2, 2) + Math.pow (Y1-y2, 2)); if ((2 + math.sqrt (2)) * Edge >= math.sqrt (Math.pow (x-x1, 2) + Math.pow (y-y1, 2)) + MATH.SQRT (Math.pow (X-X2, 2) + Math.pow (Y-y2, 2)) + MATH.SQRT (Math.pow (x-x3, 2) + Math.pow (y
    -Y3, 2)) + MATH.SQRT (Math.pow (x-x4, 2) + Math.pow (Y-y4, 2)) {return true;
  return false; }

Summarize

Well, the content of this article to this end, complete the above steps, you can complete the picture on the screen magnification, translation and rotation of the operation. Is it still very simple. Interested in the operation of their own hands, I hope this article for everyone's study and work can help, if there are questions can be exchanged message, thank you for the cloud Habitat Community support.

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.