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

132047178567943.gif
在系统的相册中,观看相片就可以用多个手指进行缩放.
要实现这个功能,只需要这几步:

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(sourceBitmapmatrixnull);
            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(sourceBitmapmatrixnull);
        }
    }
    
    //对图片进行缩放处理
    private void zoom(Canvas canvas){
        matrix.reset();
        //将图片按照比例缩放
        matrix.postScale(totalRatiototalRatio);
        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(sourceBitmapmatrixnull);
    }
    
    //对图片进行平移处理
    private void move(Canvas canvas){
        matrix.reset();
        //根据手指移动的距离计算总偏移量
        float translateX=totalTranslateX+moveDistanceX;
        float translateY=totalTranslateY+moveDistanceY;
        //按照已有的缩放比例对图片缩放
        matrix.postScale(totalRatiototalRatio);
        //根据移动距离进行偏移
        matrix.postTranslate(translateX, translateY);
        totalTranslateX=translateX;
        totalTranslateY=translateY;
        canvas.drawBitmap(sourceBitmapmatrixnull);
    }
    
    //计算两个手指的距离
    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)


转载于:https://www.cnblogs.com/aibuli/p/76d1cd14cb1dcf018198fba314bb3509.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/359586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jboss eclipse_调试生产服务器– Eclipse和JBoss展示

jboss eclipse您是否编写有错误的代码&#xff1f; 不&#xff0c;当然不是。 对于我们其余的人&#xff0c;他们确实会编写带有bug的代码&#xff0c;我想解决一个非常敏感的问题&#xff1a;调试在生产服务器上运行的应用程序。 因此&#xff0c;您的应用程序已准备好进行部…

Chrome 控制台不完全指南

Chrome的开发者工具已经强大到没朋友的地步了&#xff0c;特别是其功能丰富界面友好的console&#xff0c;使用得当可以有如下功效&#xff1a; 更高「逼格」更快「开发调试」更强「进阶级的Frontender」Bug无处遁形「Console大法好」console.log 大家都会用log&#xff0c;但鲜…

datanucleus_DataNucleus 3.0与Hibernate 3.5

datanucleus如官方产品站点所述&#xff0c; DataNucleus Access Platform是现有的最符合标准的开源Java持久性产品。 它完全符合JDO1 &#xff0c; JDO2 &#xff0c; JDO2.1 &#xff0c; JDO2.2 &#xff0c; JDO3 &#xff0c; JPA1和JPA2 Java标准。 它还符合OGC简单功能规…

Android学习笔记——Menu(二)

知识点&#xff1a;这次将继续上一篇文章没有讲完的Menu的学习&#xff0c;上下文菜单(Context menu)和弹出菜单(Popup menu)。 上下文菜单上下文菜单提供对UI界面上的特定项或上下文框架的操作&#xff0c;就如同Windows中右键菜单一样。 在Android中&#xff0c;有两种提供上…

eclipse卡慢解决办法

1.设置JVM运行内存 1.1编辑eclipse.ini 1.2 编辑eclipse.ini,设置jvm运行内存参数&#xff0c;最小内存&#xff1a;物理内存*0.2&#xff0c; 最大内存&#xff1a; 物理内存*0.6&#xff1b; 其中-vmargs为必须添加参数&#xff08;-vmargs的意思是设置JVM参数&#xff09;,…

QQ游戏百万人同时在线服务器架构实现

转载自&#xff1a;http://morton5555.blog.163.com/blog/static/976407162012013112545710/# QQ游戏于前几日终于突破了百万人同时在线的关口&#xff0c;向着更为远大的目标迈进&#xff0c;这让其它众多传统的棋牌休闲游戏平台黯然失色&#xff0c;相比之下&#xff0c;联众…

ruby和python_Ruby,Python和Java中的Web服务

ruby和python今天&#xff0c;我不得不准备一些示例来说明Web服务是可互操作的。 因此&#xff0c;我已经使用Metro使用Java创建了一个简单的Web服务&#xff0c;并在Tomcat上启动了它。 然后尝试使用Python和Ruby消耗它们。 这是全部完成的过程… Java中的Web服务 我从Java中…

USB描述符【整理】

USB描述符 USB描述符信息存储在USB设备中&#xff0c;在枚举过程中&#xff0c;USB主机会向USB设备发送GetDescriptor请求&#xff0c;USB设备在收到这个请求之后&#xff0c;会将USB描述符信息返回给USB主机&#xff0c;USB主机分析返回来的数据&#xff0c;判断出该设备是哪一…

什么是垃圾回收?

以下是我们的垃圾收集手册中的一个示例&#xff0c;该手册将在接下来的几周内发布。 同时&#xff0c;花点时间熟悉垃圾收集的基础知识-这将是本书的第一章。 乍一看&#xff0c;垃圾收集应该处理顾名思义的问题-查找并丢弃垃圾。 实际上&#xff0c;它所做的恰恰相反。 垃圾收…

Extjs弹窗-简单文本编辑框-Ext.Msg.show

var datavalue测试202109;//文本传入数据 Ext.Msg.show({ title:标题, msg:说明, width:600, height:500, prompt:true, multiline:200, closable:true, …

word模板插入文本域并调整表格某一个行的列宽度

一、插入文本域 操作步骤&#xff1a;插入&#xff08;菜单&#xff09;->文档部件&#xff08;菜单&#xff09;->域&#xff08;菜单&#xff09;->邮件合并->输入名称->确认 二、调整word表格某个单元格宽度 选中某行&#xff0c;按住ctrl键的同时&#xf…

java泛型视频教程_Java泛型快速教程

java泛型视频教程泛型是Java SE 5.0引入的一种Java功能&#xff0c;在其发布几年后&#xff0c;我发誓那里的每个Java程序员不仅会听说过&#xff0c;而且已经使用过。 关于Java泛型&#xff0c;有很多免费和商业资源&#xff0c;而我使用的最佳资源是&#xff1a; Java教程 …

Windows上的Oracle Java

我最近为基于Windows 7的笔记本电脑下载了JDK 9的早期访问版本 &#xff08;内部版本68 &#xff09;。 由于这是早期版本&#xff0c;因此当自动安装在笔记本电脑上安装主要Java Runtime Environment&#xff08;JRE&#xff09;引入了一些不太理想的问题时&#xff0c;我并不…

extjs弹出窗口查看文本内容-new Ext.Window

代码样例&#xff1a; function processscan(){ var text时间 用户 操作<br> 时间 用户 操作<br> 时间 用户 操作; var win new Ext.Window({ layout: fit, width: 700, height: 600, closeAction: hide, dra…

Ioc Autofac心得

对于这个容器注入&#xff0c;个人也不是很熟悉&#xff0c;很多还不懂&#xff0c;只会基本的操作&#xff0c;几天把它记录下来&#xff0c;说不定以后帮助就大了呢&#xff0c;这方面跟安卓差距还是挺大的 下面记录下应用的流程 步骤&#xff1a; 1.添加应用 2.重写工厂&…

深入学习Web Service系列----异步开发模式

概述 在本篇随笔中&#xff0c;通过一些简单的示例来说一下Web Service中的异步调用模式。调用Web Service方法有两种方式&#xff0c;同步调用和异步调用。同步调用是程序继续执行前等候调用的完成&#xff0c;而异步调用在后台继续时&#xff0c;程序也继续执行&#xff0c;不…

navicate导出导入表数据问题

1.导出导入json&#xff0c;如下图&#xff0c;右击表点击导出向导&#xff0c;选择json导出类型&#xff0c;根据提示导出即可。 导入时&#xff0c;右击接收的表&#xff0c;点击导入向导&#xff0c;根据提示即可快速导入&#xff08;注&#xff1a;不同系统之间导出导入易…

tongweb通过控制台简单设置确认相关常用参数

1.环境版本 jdk&#xff0c;tongweb版本确认是否正确 2.检查tongweb的 license是不是永久版本&#xff0c;试用期版本到期会停止服务。 3 JVM运行编码配置-根据系统需要配置 3.1-Dfile.encodingUTF-8 编码根据系统需要配置 4. tongweb运行内存大小--根据系统需要配置 4.1一般 …

编译原理--LL(1)分析法实验C++

一、实验项目要求 1.实验目的 根据某一文法编制调试LL&#xff08;1&#xff09;分析程序&#xff0c;以便对任意输入的符号串进行分析。本次实验的目的主要是加深对预测分析LL&#xff08;1&#xff09;分析法的理解。 2.实验要求 对下列文法&#xff0c;用LL&#xff08;…

实际中进行GC调整

调优垃圾回收与任何其他性能调优活动没有什么不同。 您需要确保了解当前的情况和期望的结果&#xff0c;而不是因为对应用程序的随机部分进行调整而产生了诱惑。 通常&#xff0c;只需执行以下过程即可&#xff1a; 陈述您的绩效目标 运行测试 测量 与目标比较 进行更改并…