android多点触控自由对图片缩放



在系统的相册中,观看相片就可以用多个手指进行缩放.

要实现这个功能,只需要这几步:

1.新建项目,在项目中新建一个ZoomImage.java

public class ZoomImageView extends View {

//初始化状态常量

public static final int STATUS_INIT=1;

//图片放大状态常量

public static final int STATUS_ZOOM_OUT=2;

//图片缩小状态常量

public static final int STATUS_ZOOM_IN=3;

//图片拖动状态的常量

public static final int STATUS_MOVE=4;

//对图片进行移动和缩放的矩阵

private Matrix matrix=new Matrix();

//需要处理的Bitmap对象

private Bitmap sourceBitmap;

//记录当前的操作状态

private int currentStatus;

//ZoomImageView的宽度

private int width;

//ZoomImageView的高度

private int height;

//记录两指同时放在屏幕上时,中心点的横坐标

private float centerPointX;

//记录两指同时放在屏幕上时,中心点的纵坐标

private float centerPointY;

//记录当前图片的宽度

private float currentBitmapWidth;

//记录当前图片的高度

private float currentBitmapHeight;

//记录上次手指移动时的横坐标

private float lastXMove=-1;

//记录上次手指移动时的纵坐标

private float lastYMove=-1;

//记录手指在横坐标上的距离

private float moveDistanceX;

//记录手指在纵坐标上的距离

private float moveDistanceY;

//记录图片在矩阵上横向偏移值

private float totalTranslateX;

//记录图片在矩阵上纵向偏移值

private float totalTranslateY;

//记录图片在矩阵上总缩放比例

private float totalRatio;

//记录手指移动的距离造成的缩放比例

private float scaledRatio;

//记录图片初始化时的缩放比例

private float initRatio;

//记录上次手指之间的距离

private double lastFingerDis;

//初始状态  设置当前操作状态为STATUS_INIT

public ZoomImageView(Context context, AttributeSet attrs) {

super(context, attrs);

currentStatus=STATUS_INIT;

}

//将待展示的图片设置进来

public void setImageBitmap(Bitmap bitmap){

sourceBitmap=bitmap;

invalidate();

}

@Override

protected void onLayout(boolean changed, int left, int top, int right,

int bottom) {

super.onLayout(changed, left, top, right, bottom);

if(changed){

width=getWidth();

height=getHeight();

}

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getActionMasked()) {

case MotionEvent.ACTION_POINTER_DOWN:

if(event.getPointerCount()==2){

lastFingerDis=distanceBetweenFingers(event);  //两指间按下的距离

}

break;

case MotionEvent.ACTION_MOVE:

if(event.getPointerCount()==1){  //如果只有一个手指在屏幕上 则为拖动模式

float xMove=event.getX();

float yMove=event.getY();

if(lastXMove==-1&&lastYMove==-1){

lastXMove=xMove;

lastYMove=yMove;

}

currentStatus=STATUS_MOVE;

moveDistanceX=xMove-lastXMove;

moveDistanceY=yMove-lastYMove;

//进行边界检查 不允许拖出边界

if(totalTranslateX+moveDistanceX>0){

moveDistanceX=0;

}

else if(width-(totalTranslateX+moveDistanceX)>currentBitmapWidth){

moveDistanceX=0;

}

if(totalTranslateY+moveDistanceY>0){

moveDistanceY=0;

}

else if(height-(totalTranslateY+moveDistanceY)>currentBitmapHeight){

moveDistanceY=0;

}

//调用onDraw()方法绘制图片

invalidate();

lastXMove=xMove;

lastYMove=yMove;

}

else if(event.getPointerCount()==2){

//有两个手指在屏幕上移动  为缩放状态

centerPointBetweenFingers(event);

double fingerDis=distanceBetweenFingers(event);

if(fingerDis>lastFingerDis){

currentStatus=STATUS_ZOOM_OUT;

}

else{

currentStatus=STATUS_ZOOM_IN;

}

//进行缩放倍数检查

if((currentStatus==STATUS_ZOOM_OUT&&totalRatio<4*initRatio)||(currentStatus==STATUS_ZOOM_IN&&totalRatio>initRatio)){

scaledRatio=(float) (fingerDis/lastFingerDis);  //需要缩放的比例

totalRatio=totalRatio*scaledRatio;

if(totalRatio>4*initRatio){

totalRatio=4*initRatio;

}

else if(totalRatio<initRatio){

totalRatio=initRatio;

}

//调用onDraw

invalidate();

lastFingerDis=fingerDis;

}

}

break;

case MotionEvent.ACTION_POINTER_UP:

if(event.getPointerCount()==2){

lastXMove=-1;

lastYMove=-1;

}

break;

case MotionEvent.ACTION_UP:

lastXMove=-1;

lastYMove=-1;

break;

default:

break;

}

return true;

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

switch (currentStatus) {

case STATUS_ZOOM_OUT:

case STATUS_ZOOM_IN:

zoom(canvas);

break;

case STATUS_MOVE:

move(canvas);

break;

case STATUS_INIT:

initBitmap(canvas);

break;

default:

canvas.drawBitmap(sourceBitmap, matrix, null);

break;

}

}

//初始化显示图片

private void initBitmap(Canvas canvas){

if(sourceBitmap!=null){

matrix.reset();

int bitmapWidth=sourceBitmap.getWidth();

int bitmapHeight=sourceBitmap.getHeight();

if(bitmapWidth>width||bitmapHeight>height){//如果图片的宽度或高度有大于屏幕宽高

if(bitmapWidth-width>bitmapHeight-height){    //判断这张图片 是宽度长  还是高度长  如果是宽度长,则按宽度的那边进行压缩  高度也等比例压缩

float radio=width/(bitmapWidth*1.0f);     //需要压缩的比例

matrix.postScale(radio,radio);             //缩放矩阵比例

float translateY=(height-(bitmapHeight*radio))/2f;   //因为是按宽度进行压缩  所以宽度应该是占满全屏  这时候还应该将图片Y轴向下移动

//在纵坐标上进行偏移 以保证图片居中显示

matrix.postTranslate(0, translateY);

totalTranslateY=translateY;

totalRatio=initRatio=radio;

}

else{

//当图片高度大于屏幕高度时

float radio=height/(bitmapHeight*1.0f);

matrix.postScale(radio, radio);

float translateX=(width-(bitmapWidth*radio))/2f;

//在横坐标上进行偏移

matrix.postTranslate(translateX, 0);//平移

totalTranslateX=translateX;

totalRatio=initRatio=radio;

}

}

else{

//当图片的宽度与高度都小于屏幕宽高时,让图片居中显示

float translateX=(width-sourceBitmap.getWidth())/2f;

float translateY=(height-sourceBitmap.getHeight())/2f;

matrix.postTranslate(translateX, translateY);

totalTranslateX=translateX;

totalTranslateY=translateY;

totalRatio=initRatio=1f;

currentBitmapHeight=bitmapHeight;

currentBitmapWidth=bitmapWidth;

}

canvas.drawBitmap(sourceBitmap, matrix, null);

}

}

//对图片进行缩放处理

private void zoom(Canvas canvas){

matrix.reset();

//将图片按照比例缩放

matrix.postScale(totalRatio, totalRatio);

float scaledWidth=sourceBitmap.getWidth()*totalRatio;

float scaledHeight=sourceBitmap.getHeight()*totalRatio;

float translateX=0f;

float translateY=0f;

//如果当前图片宽度小于屏幕宽度  则按屏幕中心点 进行水平缩放,否则按两指中线点的横坐标进行缩放

if(currentBitmapWidth<width){

translateX=(width-scaledWidth)/2f;

}

else{

translateX=totalTranslateX*scaledRatio+centerPointX*(1-scaledRatio);

//进入边界检查 ,保证图片缩放后水平方向不会偏移屏幕

if(translateX>0){

translateX=0;

}

else if(width-translateX>scaledWidth){

translateX=width-scaledWidth;

}

}

if(currentBitmapHeight<height){

translateY=(height-scaledHeight)/2f;

}

else{

translateY=totalTranslateY*scaledRatio+centerPointY*(1-scaledRatio);

//进行边界检查

if(translateY>0){

translateY=0;

}

else if(height-translateY>scaledHeight){

translateY=height-scaledHeight;

}

}

//缩放后对图片进行偏移 保证缩放后中心点位置不变

matrix.postTranslate(translateX, translateY);

totalTranslateX=translateX;

totalTranslateY=translateY;

currentBitmapWidth=scaledWidth;

currentBitmapHeight=scaledHeight;

canvas.drawBitmap(sourceBitmap, matrix, null);

}

//对图片进行平移处理

private void move(Canvas canvas){

matrix.reset();

//根据手指移动的距离计算总偏移量

float translateX=totalTranslateX+moveDistanceX;

float translateY=totalTranslateY+moveDistanceY;

//按照已有的缩放比例对图片缩放

matrix.postScale(totalRatio, totalRatio);

//根据移动距离进行偏移

matrix.postTranslate(translateX, translateY);

totalTranslateX=translateX;

totalTranslateY=translateY;

canvas.drawBitmap(sourceBitmap, matrix, null);

}

//计算两个手指的距离

private double distanceBetweenFingers(MotionEvent event){

float disX=Math.abs(event.getX(0)-event.getX(1));

float disY=Math.abs(event.getY(0)-event.getY(1));

return Math.sqrt(disX*disX+disY*disY);

}

//计算两个手指之间中心点的坐标

private void centerPointBetweenFingers(MotionEvent event){

float xPoint0=event.getX(0);

float yPoint0=event.getY(0);

float xPoint1=event.getX(1);

float yPoint1=event.getY(1);

centerPointX=(xPoint0+xPoint1)/2;

centerPointY=(yPoint0+yPoint1)/2;

}

}

2.打开activity_main.xml

<com.example.bitmaptest.ZoomImageView 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:id="@+id/zoom_image"

tools:context="com.example.bitmaptest.MainActivity" >

</com.example.bitmaptest.ZoomImageView>

3.打开MainActivity.java

public class MainActivity extends ActionBarActivity {

private Bitmap bitmap;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

ZoomImageView zoomImage=(ZoomImageView) findViewById(R.id.zoom_image);

bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

if(bitmap!=null){

zoomImage.setImageBitmap(bitmap);

}

}

}

来自为知笔记(Wiz)

时间: 2024-10-27 03:57:38

android多点触控自由对图片缩放的相关文章

Android实现图片多点触控自由伸缩

简介 作为Android开发者,我们经常需要自定义控件,比如下面我们说的实现图片的多点触控和伸缩释放,这也是由于用户已经有这样的常识了,那就是看见有图片的地方就可以点击查看大图,并且可以通过手指对图片进行伸缩和移动,如果应用没有实现这一点,那么对用户来说将会是很糟糕的体验,用户很"愤怒".所以作为Android开发者,我们的任务就是让用户"爽".哈哈哈....下面我们将通过自定义ImageView实现以上功能. 涉及技术 一.Matrix(矩阵),Android是通

Android多点触控技术实战,自由地对图片进行缩放和移动

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11100327 在上一篇文章中我带着大家一起实现了Android瀑布流照片墙的效果,虽然这种效果很炫很酷,但其实还只能算是一个半成品,因为照片墙中所有的图片都是只能看不能点的.因此本篇文章中,我们就来对这一功能进行完善,加入点击图片就能浏览大图的功能,并且在浏览大图的时候还可以通过多点触控的方式对图片进行缩放. 如果你还没有看过 Android瀑布流照片墙实现,体验不规则排列的美感

Android多点触控(图片的缩放Demo)

本文主要介绍Android的多点触控,使用了一个图片缩放的实例,来更好的说明其原理.需要实现OnTouchListener接口,重写其中的onTouch方法. 实现效果图: 源代码: 布局文件: activity_main: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools&quo

Android多点触控技术,实现对图片的放大缩小平移,惯性滑动等功能

首先推荐一下鸿洋大大的打造个性的图片预览与多点触控视频教程,这套教程教我们一步一步实现了多点触控实现对图片的平移和缩放的功能,这篇文章我将在鸿洋大大的基础之上做了一些扩展功能: 1.图片的惯性滑动 2.图片缩放小于正常比例时,松手会自动回弹成正常比例 3.图片缩放大于最大比例时,松手会自动回弹成最大比例 实现图片的缩放,平移,双击缩放等基本功能的代码如下,每一行代码我都做了详细的注释 public class ZoomImageView extends ImageView implements

Android多点触控技术

1 简介 Android多点触控在本质上需要LCD驱动和程序本身设计上支持,目前市面上HTC.Motorola和Samsung等知名厂商只要使用电容屏触控原理的手机均可以支持多点触控Multitouch技术,对于网页缩放.手势操作上有更好的用户体验. 在Android平台上事件均使用了MotionEvent对象方式处理,比如开始触控时会触发ACTION_DOWN,而移动操作时为 ACTION_MOVE,最终放开手指时触发ACTION_UP事件.当然还有用户无规则的操作可能触发ACTION_CAN

unity3d 触屏多点触控(旋转与缩放)

unity3d 触屏多点触控(旋转与缩放) /*Touch OrbitProgrammed by: Randal J. Phillips (Caliber Mengsk)Original Creation Date: 12/16/2011Last Updated:                   12/16/2011Desctiption: Simple orbit by one touch and drag, as well as pinch to zoom with two finger

MultiTouch————多点触控,伸缩图片,变换图片位置

前言:当今的手机都支持多点触控功能(可以进行图片伸缩,变换位置),但是我们程序员要怎样结合硬件去实现这个功能呢? 跟随我一起,来学习这个功能 国际惯例:先上DEMO免费下载地址:http://download.csdn.net/detail/cnwutianhao/9443667 示例图片: 我是用Genymotion录制的,没有真机上多点触控显示的效果那么好,大家在真机上跑程序,会体会到多点触控功能.(注:Genymotion多点触控快捷键是 ctrl+鼠标指针上下拖动) 具体代码实现: 布局

关于android多点触控

最近项目需要一个多点触控缩放的功能.然后上网查了下资料 总结一下: 首先android sdk版本很重要,比如你在AndroidManifest.xml中指定android:minSdkVersion="4"  并且建工程的时候选的是android 2.2就表示你的应用兼容android1.6~android2.2 之间的版本.但是多点触控的API在1.6~~2,1~~,2,2~~三个版本中都是不一样的.比如android2.2中onTouchEvent(MotionEvent eve

Android多点触控MultiTouch浅析

申明: 参考:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2013/0226/914.html 下面实现如何通过应用层支持多点触控操作,对于常规的控件触控操实现onTouchEvent()方法来处理.同时对onTouchEvent方法的参数MotionEvent进行一些了解. 正文: 下面会用两个应用示例来初步学习一下Android中的多点触控. 示例一(DemoMultiTouch-Canvas): 核心技术介绍 本示例是在Sur