当前位置: 移动技术网 > IT编程>移动开发>Android > Android手势滑动实现两点触摸缩放图片

Android手势滑动实现两点触摸缩放图片

2019年07月24日  | 移动技术网IT编程  | 我要评论

郭纯美,刺角瓜,昆明 三对夫妻

学习安卓手势滑动,多点触摸放大缩小图片,分享给大家供大家参考,具体代码如下
1.布局文件如下main.xml

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical" >

 <!-- 引用自定义控件 -->
 <com.ymw.zoomimage.zoomimageview
  android:id="@+id/image"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" >
 </com.ymw.zoomimage.zoomimageview>

</linearlayout>

2.自定义缩放图片控件zoomimageview.java代码:

package com.ymw.zoomimage;

import java.util.observable;
import java.util.observer;

import android.content.context;
import android.graphics.bitmap;
import android.graphics.canvas;
import android.graphics.paint;
import android.graphics.rect;
import android.util.attributeset;
import android.util.log;
import android.view.motionevent;
import android.view.view;

public class zoomimageview extends view implements observer {

 /** paint object used when drawing bitmap. */
 private final paint mpaint = new paint(paint.filter_bitmap_flag);

 /** rectangle used (and re-used) for cropping source image. */
 private final rect mrectsrc = new rect();

 /** rectangle used (and re-used) for specifying drawing area on canvas. */
 private final rect mrectdst = new rect();

 /** object holding aspect quotient */
 private final aspectquotient maspectquotient = new aspectquotient();

 /** the bitmap that we're zooming in, and drawing on the screen. */
 private bitmap mbitmap;

 /** state of the zoom. */
 private zoomstate mstate;

 private basiczoomcontrol mzoomcontrol;
 private basiczoomlistener mzoomlistener;

 public zoomimageview(context context, attributeset attrs) {
  super(context, attrs);

  mzoomcontrol = new basiczoomcontrol();

  mzoomlistener = new basiczoomlistener();
  mzoomlistener.setzoomcontrol(mzoomcontrol);

  setzoomstate(mzoomcontrol.getzoomstate());

  setontouchlistener(mzoomlistener);

  mzoomcontrol.setaspectquotient(getaspectquotient());
 }

 public void zoomimage(float f, float x, float y) {
  mzoomcontrol.zoom(f, x, y);
 }

 public void setimage(bitmap bitmap) {
  mbitmap = bitmap;

  maspectquotient.updateaspectquotient(getwidth(), getheight(),
    mbitmap.getwidth(), mbitmap.getheight());
  maspectquotient.notifyobservers();

  invalidate();
 }

 private void setzoomstate(zoomstate state) {
  if (mstate != null) {
   mstate.deleteobserver(this);
  }

  mstate = state;
  mstate.addobserver(this);

  invalidate();
 }

 private aspectquotient getaspectquotient() {
  return maspectquotient;
 }

 @override
 protected void ondraw(canvas canvas) {
  if (mbitmap != null && mstate != null) {

   log.d("zoomimageview", "ondraw");

   final float aspectquotient = maspectquotient.get();

   final int viewwidth = getwidth();
   final int viewheight = getheight();
   final int bitmapwidth = mbitmap.getwidth();
   final int bitmapheight = mbitmap.getheight();

   log.d("zoomimageview", "viewwidth = " + viewwidth);
   log.d("zoomimageview", "viewheight = " + viewheight);
   log.d("zoomimageview", "bitmapwidth = " + bitmapwidth);
   log.d("zoomimageview", "bitmapheight = " + bitmapheight);

   final float panx = mstate.getpanx();
   final float pany = mstate.getpany();
   final float zoomx = mstate.getzoomx(aspectquotient) * viewwidth
     / bitmapwidth;
   final float zoomy = mstate.getzoomy(aspectquotient) * viewheight
     / bitmapheight;

   // setup source and destination rectangles
   mrectsrc.left = (int) (panx * bitmapwidth - viewwidth / (zoomx * 2));
   mrectsrc.top = (int) (pany * bitmapheight - viewheight
     / (zoomy * 2));
   mrectsrc.right = (int) (mrectsrc.left + viewwidth / zoomx);
   mrectsrc.bottom = (int) (mrectsrc.top + viewheight / zoomy);
   // mrectdst.left = getleft();
   mrectdst.left = 0;
   mrectdst.top = 0;
   // mrectdst.right = getright();
   mrectdst.right = getwidth();
   mrectdst.bottom = getheight();

   // adjust source rectangle so that it fits within the source image.
   if (mrectsrc.left < 0) {
    mrectdst.left += -mrectsrc.left * zoomx;
    mrectsrc.left = 0;
   }
   if (mrectsrc.right > bitmapwidth) {
    mrectdst.right -= (mrectsrc.right - bitmapwidth) * zoomx;
    mrectsrc.right = bitmapwidth;
   }
   if (mrectsrc.top < 0) {
    mrectdst.top += -mrectsrc.top * zoomy;
    mrectsrc.top = 0;
   }
   if (mrectsrc.bottom > bitmapheight) {
    mrectdst.bottom -= (mrectsrc.bottom - bitmapheight) * zoomy;
    mrectsrc.bottom = bitmapheight;
   }

   mrectdst.left = 0;
   mrectdst.top = 0;
   mrectdst.right = viewwidth;
   mrectdst.bottom = viewheight;

   log.d("zoomimageview", "mrectsrc.top" + mrectsrc.top);
   log.d("zoomimageview", "mrectsrc.bottom" + mrectsrc.bottom);
   log.d("zoomimageview", "mrectsrc.left" + mrectsrc.left);
   log.d("zoomimageview", "mrectsrc.right" + mrectsrc.right);

   log.d("zoomimageview", "mrectdst.top" + mrectdst.top);
   log.d("zoomimageview", "mrectdst.bottom" + mrectdst.bottom);
   log.d("zoomimageview", "mrectdst.left" + mrectdst.left);
   log.d("zoomimageview", "mrectdst.right" + mrectdst.right);

   canvas.drawbitmap(mbitmap, mrectsrc, mrectdst, mpaint);
  }
 }

 @override
 protected void onlayout(boolean changed, int left, int top, int right,
   int bottom) {
  super.onlayout(changed, left, top, right, bottom);

  maspectquotient.updateaspectquotient(right - left, bottom - top,
    mbitmap.getwidth(), mbitmap.getheight());
  maspectquotient.notifyobservers();
 }

 @override
 public void update(observable observable, object data) {
  invalidate();
 }

 private class basiczoomlistener implements view.ontouchlistener {

  /** zoom control to manipulate */
  private basiczoomcontrol mzoomcontrol;

  private float mfirstx = -1;
  private float mfirsty = -1;
  private float msecondx = -1;
  private float msecondy = -1;

  private int moldcounts = 0;

  /**
   * sets the zoom control to manipulate
   * 
   * @param control
   *   zoom control
   */
  public void setzoomcontrol(basiczoomcontrol control) {
   mzoomcontrol = control;
  }

  public boolean ontouch(view v, motionevent event) {

   switch (event.getaction()) {
   case motionevent.action_down:
    moldcounts = 1;
    mfirstx = event.getx();
    mfirsty = event.gety();
    break;
   case motionevent.action_move: {
    float ffirstx = event.getx();
    float ffirsty = event.gety();

    int ncounts = event.getpointercount();

    if (1 == ncounts) {
     moldcounts = 1;
     float dx = (ffirstx - mfirstx) / v.getwidth();
     float dy = (ffirsty - mfirsty) / v.getheight();
     mzoomcontrol.pan(-dx, -dy);
    } else if (1 == moldcounts) {
     msecondx = event.getx(event.getpointerid(ncounts - 1));
     msecondy = event.gety(event.getpointerid(ncounts - 1));
     moldcounts = ncounts;
    } else {
     float fsecondx = event
       .getx(event.getpointerid(ncounts - 1));
     float fsecondy = event
       .gety(event.getpointerid(ncounts - 1));

     double nlengthold = getlength(mfirstx, mfirsty, msecondx,
       msecondy);
     double nlengthnow = getlength(ffirstx, ffirsty, fsecondx,
       fsecondy);

     float d = (float) ((nlengthnow - nlengthold) / v.getwidth());

     mzoomcontrol.zoom((float) math.pow(20, d),
       ((ffirstx + fsecondx) / 2 / v.getwidth()),
       ((ffirsty + fsecondy) / 2 / v.getheight()));

     msecondx = fsecondx;
     msecondy = fsecondy;
    }
    mfirstx = ffirstx;
    mfirsty = ffirsty;

    break;
   }

   }

   return true;
  }

  private double getlength(float x1, float y1, float x2, float y2) {
   return math.sqrt(math.pow(x1 - x2, 2) + math.pow(y1 - y2, 2));
  }
 }

 private class basiczoomcontrol implements observer {

  /** minimum zoom level limit */
  private static final float min_zoom = 1;

  /** maximum zoom level limit */
  private static final float max_zoom = 16;

  /** zoom state under control */
  private final zoomstate mstate = new zoomstate();

  /** object holding aspect quotient of view and content */
  private aspectquotient maspectquotient;

  /**
   * set reference object holding aspect quotient
   * 
   * @param aspectquotient
   *   object holding aspect quotient
   */
  public void setaspectquotient(aspectquotient aspectquotient) {
   if (maspectquotient != null) {
    maspectquotient.deleteobserver(this);
   }

   maspectquotient = aspectquotient;
   maspectquotient.addobserver(this);
  }

  /**
   * get zoom state being controlled
   * 
   * @return the zoom state
   */
  public zoomstate getzoomstate() {
   return mstate;
  }

  /**
   * zoom
   * 
   * @param f
   *   factor of zoom to apply
   * @param x
   *   x-coordinate of invariant position
   * @param y
   *   y-coordinate of invariant position
   */
  public void zoom(float f, float x, float y) {

   // log.d("zoom", "zoom f = " + f);

   final float aspectquotient = maspectquotient.get();

   final float prevzoomx = mstate.getzoomx(aspectquotient);
   final float prevzoomy = mstate.getzoomy(aspectquotient);

   mstate.setzoom(mstate.getzoom() * f);
   limitzoom();

   final float newzoomx = mstate.getzoomx(aspectquotient);
   final float newzoomy = mstate.getzoomy(aspectquotient);

   // pan to keep x and y coordinate invariant
   mstate.setpanx(mstate.getpanx() + (x - .5f)
     * (1f / prevzoomx - 1f / newzoomx));
   mstate.setpany(mstate.getpany() + (y - .5f)
     * (1f / prevzoomy - 1f / newzoomy));

   limitpan();

   mstate.notifyobservers();
  }

  /**
   * pan
   * 
   * @param dx
   *   amount to pan in x-dimension
   * @param dy
   *   amount to pan in y-dimension
   */
  public void pan(float dx, float dy) {
   final float aspectquotient = maspectquotient.get();

   mstate.setpanx(mstate.getpanx() + dx
     / mstate.getzoomx(aspectquotient));
   mstate.setpany(mstate.getpany() + dy
     / mstate.getzoomy(aspectquotient));

   limitpan();

   mstate.notifyobservers();
  }

  /**
   * help function to figure out max delta of pan from center position.
   * 
   * @param zoom
   *   zoom value
   * @return max delta of pan
   */
  private float getmaxpandelta(float zoom) {
   return math.max(0f, .5f * ((zoom - 1) / zoom));
  }

  /**
   * force zoom to stay within limits
   */
  private void limitzoom() {
   if (mstate.getzoom() < min_zoom) {
    mstate.setzoom(min_zoom);
   } else if (mstate.getzoom() > max_zoom) {
    mstate.setzoom(max_zoom);
   }
  }

  /**
   * force pan to stay within limits
   */
  private void limitpan() {
   final float aspectquotient = maspectquotient.get();

   final float zoomx = mstate.getzoomx(aspectquotient);
   final float zoomy = mstate.getzoomy(aspectquotient);

   final float panminx = .5f - getmaxpandelta(zoomx);
   final float panmaxx = .5f + getmaxpandelta(zoomx);
   final float panminy = .5f - getmaxpandelta(zoomy);
   final float panmaxy = .5f + getmaxpandelta(zoomy);

   if (mstate.getpanx() < panminx) {
    mstate.setpanx(panminx);
   }
   if (mstate.getpanx() > panmaxx) {
    mstate.setpanx(panmaxx);
   }
   if (mstate.getpany() < panminy) {
    mstate.setpany(panminy);
   }
   if (mstate.getpany() > panmaxy) {
    mstate.setpany(panmaxy);
   }
  }

  // observable interface implementation

  public void update(observable observable, object data) {
   limitzoom();
   limitpan();
  }
 }

 private class aspectquotient extends observable {

  /**
   * aspect quotient
   */
  private float maspectquotient;

  // public methods

  /**
   * gets aspect quotient
   * 
   * @return the aspect quotient
   */
  public float get() {
   return maspectquotient;
  }

  /**
   * updates and recalculates aspect quotient based on supplied view and
   * content dimensions.
   * 
   * @param viewwidth
   *   width of view
   * @param viewheight
   *   height of view
   * @param contentwidth
   *   width of content
   * @param contentheight
   *   height of content
   */
  public void updateaspectquotient(float viewwidth, float viewheight,
    float contentwidth, float contentheight) {
   final float aspectquotient = (contentwidth / contentheight)
     / (viewwidth / viewheight);

   if (aspectquotient != maspectquotient) {
    maspectquotient = aspectquotient;
    setchanged();
   }
  }
 }

 private class zoomstate extends observable {
  /**
   * zoom level a value of 1.0 means the content fits the view.
   */
  private float mzoom;

  /**
   * pan position x-coordinate x-coordinate of zoom window center
   * position, relative to the width of the content.
   */
  private float mpanx;

  /**
   * pan position y-coordinate y-coordinate of zoom window center
   * position, relative to the height of the content.
   */
  private float mpany;

  // public methods

  /**
   * get current x-pan
   * 
   * @return current x-pan
   */
  public float getpanx() {
   return mpanx;
  }

  /**
   * get current y-pan
   * 
   * @return current y-pan
   */
  public float getpany() {
   return mpany;
  }

  /**
   * get current zoom value
   * 
   * @return current zoom value
   */
  public float getzoom() {
   return mzoom;
  }

  /**
   * help function for calculating current zoom value in x-dimension
   * 
   * @param aspectquotient
   *   (aspect ratio content) / (aspect ratio view)
   * @return current zoom value in x-dimension
   */
  public float getzoomx(float aspectquotient) {
   return math.min(mzoom, mzoom * aspectquotient);
  }

  /**
   * help function for calculating current zoom value in y-dimension
   * 
   * @param aspectquotient
   *   (aspect ratio content) / (aspect ratio view)
   * @return current zoom value in y-dimension
   */
  public float getzoomy(float aspectquotient) {
   return math.min(mzoom, mzoom / aspectquotient);
  }

  /**
   * set pan-x
   * 
   * @param panx
   *   pan-x value to set
   */
  public void setpanx(float panx) {
   if (panx != mpanx) {
    mpanx = panx;
    setchanged();
   }
  }

  /**
   * set pan-y
   * 
   * @param pany
   *   pan-y value to set
   */
  public void setpany(float pany) {
   if (pany != mpany) {
    mpany = pany;
    setchanged();
   }
  }

  /**
   * set zoom
   * 
   * @param zoom
   *   zoom value to set
   */
  public void setzoom(float zoom) {
   if (zoom != mzoom) {
    mzoom = zoom;
    setchanged();
   }
  }
 }
}

3.工程主文件mainactivity.java代码:

package com.ymw.zoomimage;

import android.app.activity;
import android.graphics.bitmap;
import android.graphics.bitmapfactory;
import android.os.bundle;

public class mainactivity extends activity {

 private zoomimageview zoomimg;

 @override
 public void oncreate(bundle savedinstancestate) {
  super.oncreate(savedinstancestate);
  setcontentview(r.layout.main);
  zoomimg = (zoomimageview) findviewbyid(r.id.image);
  bitmap bitmap = bitmapfactory.decoderesource(this.getresources(),
    r.drawable.a);
  zoomimg.setimage(bitmap);

 }
}

以上就是android多点触摸放大缩小图片的示例代码,希望对大家的学习有所帮助。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网