zoukankan      html  css  js  c++  java
  • 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(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);
            }
        }
    }  




    qq3061280@163.com
  • 相关阅读:
    OpenStack报错:MessagingTimeout: Timed out waiting for a reply to message ID
    Missing value auth-url required for auth plugin password
    解决eth0网卡无法自动加载的问题
    Linux中一个网卡含有多个IP,将从IP升级为主IP的方法
    Ubuntu系统上双节点部署OpenStack
    Ubuntu系统上All-in-one部署OpenStack
    ubuntu系统中添加DNS服务器地址后诡异消失的解决办法
    解决Ubuntu14.04安装Chrome浏览器打不开的问题
    搭建HBase的本地模式、伪分布式、全分布式和HA模式
    PostgreSQL 与 MySQL 相比,优势何在?【转】
  • 原文地址:https://www.cnblogs.com/aibuli/p/76d1cd14cb1dcf018198fba314bb3509.html
Copyright © 2011-2022 走看看