Android realizes gesture sliding multi-point touch zoom panning Image effect (b) _android

Source: Internet
Author: User
Tags gety object object

The previous article has already brought everybody to realize the free enlargement to reduce the picture, introduced the next matrix simply; Please refer to: Android to achieve gesture sliding multi-touch zoom translation Image effect, this article continues to improve our imageview.

First add the amplification after the move.

1, free to move

We are in the ontouchevent, plus the moving code, of course, must be longer or wider than the screen can move ~ ~ ~

@Override public boolean Ontouch (View V, motionevent event) {mscalegesturedetector.ontouchevent (event);
  float x = 0, y = 0;
  Get the number of touch points final int pointercount = Event.getpointercount ();
   Gets the x and y mean values for multiple touch points for (int i = 0; i < Pointercount; i++) {x + + event.getx (i);
  Y + + event.gety (i);
  } x = X/pointercount;
 
  y = Y/pointercount;
   /** * Reset mlasx when the touch point changes, Mlasty/if (Pointercount!= lastpointercount) {Iscandrag = false;
   MLASTX = x;
  Mlasty = y;
 
  } lastpointercount = Pointercount;
   Switch (event.getaction ()) {case MOTIONEVENT.ACTION_MOVE:LOG.E (TAG, "action_move");
   float dx = X-MLASTX;
    
   float dy = y-mlasty;
   if (!iscandrag) {Iscandrag = Iscandrag (dx, dy);
    } if (Iscandrag) {RECTF RECTF = GETMATRIXRECTF ();
     if (getdrawable ()!= null) {ischeckleftandright = Ischecktopandbottom = true;
   If the width is less than the screen width, it is prohibited to move left or right if (Rectf.width () < GetWidth ()) {   DX = 0;
     Ischeckleftandright = false;
      //If the height of the screen is low, it is prohibited to move up or down if (Rectf.height () < GetHeight ()) {dy = 0;
     Ischecktopandbottom = false;
     } mscalematrix.posttranslate (dx, dy);
     Checkmatrixbounds ();
    Setimagematrix (Mscalematrix);
   } MLASTX = x;
   Mlasty = y;
 
  Break
   Case MotionEvent.ACTION_UP:case MOTIONEVENT.ACTION_CANCEL:LOG.E (TAG, "action_up");
   Lastpointercount = 0;
  Break
 return true;
 }

First we get the number of touch points, then we find the average of multiple touch points, set to our Mlastx, mlasty, and then when we move, we get dx, dy, after the range check, Call Mscalematrix.posttranslate to set the offset, of course, after the setup is completed, you need to check again, you can not move the picture and screen boundaries appear white edge, after the completion of the check, call Setimagematrix.
here: Note that we do not have a replication action_dowm, because, Action_down in the case of multi-touch, as long as one finger pressed state, the other finger press will not trigger the Action_down again, but after multiple fingers, The average of the touch points will change a lot, so we don't use Action_down. Whenever the number of touch points changes, we will be with the new current mlastx,mlasty.

Here are the two private methods used above, one for checking boundaries, and one for dragging operations:

/**
  * When moving, the boundary is judged, the main judgement is wide or higher than the screen of the *
  *
 private void Checkmatrixbounds ()
 {
  RECTF rect = GETMATRIXRECTF ( );
 
  Float deltax = 0, DeltaY = 0;
  Final float viewwidth = getwidth ();
  Final float viewheight = GetHeight ();
  Determines whether the picture appears to exceed the screen boundary if it is moved or scaled
  (rect.top > 0 && ischecktopandbottom)
  {
   deltay =-rect.top;
  }
  if (Rect.bottom < viewheight && Ischecktopandbottom)
  {
   DeltaY = Viewheight-rect.bottom;
  }
  if (Rect.left > 0 && ischeckleftandright)
  {
   deltax =-rect.left;
  }
  if (Rect.right < viewwidth && ischeckleftandright)
  {
   deltax = viewwidth-rect.right;
  }
  Mscalematrix.posttranslate (DeltaX, DeltaY);
 }
 
 /**
  * Whether it is the driving behavior
  * 
  @param dx *
  @param dy
  *
  @return
 /Private Boolean Iscandrag ( Float dx)
 {return math.sqrt (
  DX * dx) + (dy * dy)) >= mtouchslop;
 }

In this way, we can be happy to enlarge, shrink and move.
Effect Picture: This time to change a man's picture, we jailbreak one of the protagonist, tbug~

Our zoom + move is done.

2, double click Zoom in and Zoom out

When it comes to double click events, our Gesturedetector is finally coming up, this dude can catch a double click event ~ ~

1), the use of Gesturedetector

Because Gesturedetector sets the listener, the method is a bunch of ways, and we just need to ondoubletap this callback, so we're going to use one of its inner class simpleongesturelistener to implement an empty implementation of the other methods of the interface.

But there are a couple of questions that need to be discussed before we can start our code:

How do we double click the size change?

I am like this, according to the current zoom value, if it is less than 2, we double-click directly to the original image twice times; if it is between 2,4, we double click directly for the first 4 times times, the other state is 4 times times, double click to restore to the initial size.

If you think this is not appropriate, you can adjust according to your hobby.

We double-click the change, need an animation , such as our example of the demo diagram, the picture is very large, full screen when initscale=0.5 left, if double click into 2, that is, four times times larger, without a transition effect, to the user's feeling will be particularly poor. So, we're going to use Postdelay to execute a runnable,runnable of course again based on the scaling value.

First, we complete the initialization of gesturedetector in the construction method, and set up Ondoubletap listening

Public Zoomimageview (context, AttributeSet attrs) {Super (context, attrs);
  Mscalegesturedetector = new Scalegesturedetector (context, this);  Mgesturedetector = new Gesturedetector (context, new Simpleongesturelistener () {@Override public boolean
 
      Ondoubletap (motionevent e) {if (Isautoscale = = true) return true;
      float x = E.getx ();
      Float y = e.gety ();
      LOG.E ("Doubletap", Getscale () + "," + Initscale);  if (Getscale () < Scale_mid) {ZoomImageView.this.postDelayed (new autoscalerunnable (Scale_mid, X,
       y), 16);
      Isautoscale = true; else if (Getscale () >= scale_mid && Getscale () < Scale_max) {ZoomImageView.this.post
       Delayed (new autoscalerunnable (Scale_max, x, y), 16);
      Isautoscale = true;
       else {ZoomImageView.this.postDelayed (new autoscalerunnable (Initscale, x, y), 16);
Isautoscale = true;      return true;
  }
    });
  Mtouchslop = Viewconfiguration.get (context). Getscaledtouchslop ();
  Super.setscaletype (Scaletype.matrix);
 This.setontouchlistener (this);
 }
    • 1, when double click, first judge whether is automatically scaling, if in, direct retrun;
    • 2, then entered our if, if of course is scale less than 2, then through view. Send a runnable for execution;

Here's a look at our runnable code:

/** * Automatic Scaling task * * @author Zhy */Private class Autoscalerunnable implements Runnable {static final Flo
  at bigger = 1.07f;
  Static final float smaller = 0.93f;
  private float Mtargetscale;
 
  private float Tmpscale;
  /** * Zoom Center * * Private float X;
 
  private float y; /** * Incoming target scaling value, judging by target value and current value, should be enlarged or reduced * * @param targetscale/public autoscalerunnable (float Targetscale, FL
   Oat x, float y) {this.mtargetscale = Targetscale;
   this.x = x;
   This.y = y;
   if (Getscale () < Mtargetscale) {Tmpscale = bigger;
   else {tmpscale = smaller;
   } @Override public void Run () {//Zoom Mscalematrix.postscale (Tmpscale, Tmpscale, x, y);
   Checkborderandcenterwhenscale ();
 
   Setimagematrix (Mscalematrix);
   Final float Currentscale = Getscale (); If the value is within the legal range, continue scaling if (((Tmpscale > 1f) && (Currentscale < Mtargetscale) | | ((Tmpscale < 1f) && (Mtargetscale < CurrentscaLe))) {ZoomImageView.this.postDelayed (this, 16);
    else//set to target scaling {final float deltascale = Mtargetscale/currentscale;
    Mscalematrix.postscale (Deltascale, Deltascale, x, y);
    Checkborderandcenterwhenscale ();
    Setimagematrix (Mscalematrix);
   Isautoscale = false;
 }
 
  }
 }

The code is finished, we still need to pass our event to it, still in the Ontouch method:

@Override Public
 Boolean Ontouch (View V, motionevent event)
 {
  if (mgesturedetector.ontouchevent (event)) return
   true;

OK, double-click the zoom in and zoom out of the function is done.
3, dealing with the conflict between the Viewpager

Directly to our picture as Viewpager item, it is conceivable that there must be conflict ~ ~

1), Layout 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 ">
 
  
 < /android.support.v4.view.viewpager>
 
</relativelayout>

2), Activity code

Package Com.zhy.zhy_scalegesturedetector02;
Import android.app.Activity;
Import Android.os.Bundle;
Import Android.support.v4.view.PagerAdapter;
Import Android.support.v4.view.ViewPager;
Import Android.view.View;
Import Android.view.ViewGroup;
 
Import Android.widget.ImageView;
 
Import Com.zhy.view.ZoomImageView;
 public class Mainactivity extends activity {private Viewpager Mviewpager;
 Private int[] Mimgs = new int[] {r.drawable.tbug, r.drawable.a, r.drawable.xx};
 
 Private imageview[] Mimageviews = new Imageview[mimgs.length];
  @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
   
  Setcontentview (R.LAYOUT.VP);
  Mviewpager = (Viewpager) Findviewbyid (R.id.id_viewpager); Mviewpager.setadapter (New Pageradapter () {@Override public Object instantiateitem (viewgroup container, int posi
    tion) {Zoomimageview ImageView = new Zoomimageview (Getapplicationcontext ()); Imageview.setimageresource (Mimgs[poSition]);
    Container.addview (ImageView);
    Mimageviews[position] = ImageView;
   return ImageView; @Override public void Destroyitem (ViewGroup container, int position, object object) {Container.remo
   Veview (Mimageviews[position]);
   @Override public boolean isviewfromobject (View arg0, Object arg1) {return arg0 = = Arg1;
   @Override public int GetCount () {return mimgs.length;
 
 }
  });
 }
}

Now run directly, found Viewpager good, but our picture enlarged, mobile and Viewpager conflict, and can not move ~ ... Rub the towel ...
3), Handling conflicts

Now we quickly think about it, remember the previous study of the event distribution mechanism, our zoomimageview in Viewpager, if we do not want to be intercepted, then how to do?
The first thing we do not want to be intercepted is that our width or height is greater than the width or height of the screen, because we can move at this time, we do not want to be intercepted. Next, do not want to be intercepted:

GetParent (). Requestdisallowintercepttouchevent (True);

A line of code is sufficient, if you are not intercepted in the event distribution is not clear, you can refer to: How not to be intercepted.

Put it together. Our code is:

Switch (event.getaction ())
  {case
  Motionevent.action_down:
   if (Rectf.width () > getwidth () | | Rectf.height () > GetHeight ())
   {
    getparent (). Requestdisallowintercepttouchevent (True);
   break;
  Case Motionevent.action_move:
   if (Rectf.width () > getwidth () | | rectf.height () > GetHeight ())
   {
    GetParent (). Requestdisallowintercepttouchevent (True);
   }

When the width or height is greater than the width or height of the screen, the drag effect is thought to be moving the picture, whereas the Viewpager to handle it.

The effect at this point:

OK, now we've settled the conflict with Viewpager.

4, reach the boundary incident to Viewpager processing

Some users may also hope that when the picture reaches the boundary, can not drag the time, can give the event to Viewpager

Then in the Action_move, when the judge has reached the border and is still pulling, the event is given to Viewpager

if (Iscandrag)
   {
 
    if (getdrawable ()!= null)
    {
     if (GETMATRIXRECTF (). left = = 0 && dx > 0)
     { C7/>getparent (). Requestdisallowintercepttouchevent (false);
 
     if (GETMATRIXRECTF (). Right = = getwidth () && DX < 0)
     {
      getparent (). Requestdisallowintercepttouchevent (false);
     

The effect at this point:

Here, our Android gesture detection to create a picture preview effect that supports scaling translation end ~~!

It is recommended to enlarge the double-click to 4 times times and comment out an IF

      Else if (Getscale () >= scale_mid
//        && Getscale () < Scale_max)
//      {/
/       ZoomImageView.this.postDelayed (
//         new Autoscalerunnable (Scale_max, x, y),);       Isautoscale = true;
//      }

The above is the entire content of this article, I hope to help you learn, we can also practice the Android gestures to move the multi-touch zoom panning image effect.

Related Article

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.