package com.example.myimageview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

public class MyImageView extends ImageView{
        Matrix matrix = new Matrix();  
        Matrix savedMatrix = new Matrix();  
        /**位图对象*/  
        private Bitmap bitmap = null;  
        /** 屏幕的分辨率*/  
        private DisplayMetrics dm;  
      
        /** 最小缩放比例*/  
        float minScaleR = 1.0f;  
          
        /** 最大缩放比例*/  
        static final float MAX_SCALE = 15f;  
        /** 初始状态*/  
        static final int NONE = 0;  
        /** 拖动*/  
        static final int DRAG = 1;  
        /** 缩放*/  
        static final int ZOOM = 2;  
        /** 当前模式*/  
        int mode = NONE;  
        /** 存储float类型的x,y值,就是你点下的坐标的X和Y*/  
        PointF prev = new PointF();  
        PointF mid = new PointF();  
        float dist = 1f;  
        public MyImageView(Context context) {  
            super(context);  
            setupView();  
        }  
          
        public MyImageView(Context context, AttributeSet attrs) {  
            super(context, attrs);  
            setupView();  
        }  
          
          
        public void setupView(){  
            Context context = getContext();  
            //获取屏幕分辨率,需要根据分辨率来使用图片居中  
            dm = context.getResources().getDisplayMetrics();  
              
            //根据MyImageView来获取bitmap对象  
            BitmapDrawable bd = (BitmapDrawable)this.getDrawable();  
            if(bd != null){  
                bitmap = bd.getBitmap();  
            }  
    
            //设置ScaleType为ScaleType.MATRIX,这一步很重要  
            this.setScaleType(ScaleType.MATRIX);  
            this.setImageBitmap(bitmap);  
              
            //bitmap为空就不调用center函数  
            if(bitmap != null){  
                center(true, true);  
            }  
            this.setImageMatrix(matrix);  
            this.setOnTouchListener(new OnTouchListener() {  
                @Override  
                public boolean onTouch(View v, MotionEvent event) {  
                     switch (event.getAction() & MotionEvent.ACTION_MASK) {  
                        // 主点按下  
                        case MotionEvent.ACTION_DOWN:  
                            savedMatrix.set(matrix);  
                            prev.set(event.getX(), event.getY());  
                            mode = DRAG;  
                            break;  
                        // 副点按下  
                        case MotionEvent.ACTION_POINTER_DOWN:  
                            dist = spacing(event);  
                            // 如果连续两点距离大于10,则判定为多点模式  
                            if (spacing(event) > 10f) {  
                                savedMatrix.set(matrix);  
                                midPoint(mid, event);  
                                mode = ZOOM;  
                            }  
                            break;  
                        case MotionEvent.ACTION_UP:{  
                            break;  
                        }  
                        case MotionEvent.ACTION_POINTER_UP:  
                            mode = NONE;  
                            //savedMatrix.set(matrix);  
                            break;  
                        case MotionEvent.ACTION_MOVE:  
                            if (mode == DRAG) {  
                                matrix.set(savedMatrix);  
                                matrix.postTranslate(event.getX() - prev.x, event.getY()  
                                        - prev.y);  
                            } else if (mode == ZOOM) {  
                                float newDist = spacing(event);  
                                if (newDist > 10f) {  
                                    matrix.set(savedMatrix);  
                                    float tScale = newDist / dist;  
                                    matrix.postScale(tScale, tScale, mid.x, mid.y);  
                                }  
                            }  
                            break;  
                        }  
                        MyImageView.this.setImageMatrix(matrix);  
                        CheckView();  
                        return true;  
                }  
            });  
        }    
        /**
         * 横向、纵向居中
         */  
        protected void center(boolean horizontal, boolean vertical) {  
            Matrix m = new Matrix();  
            m.set(matrix);  
            RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());  
            m.mapRect(rect);  
      
            float height = rect.height();  
            float width = rect.width();  
      
            float deltaX = 0, deltaY = 0;  
      
            if (vertical) {  
                // 图片小于屏幕大小,则居中显示。大于屏幕,上方留空则往上移,下方留空则往下移  
                int screenHeight = dm.heightPixels;  
                if (height < screenHeight) {  
                    deltaY = (screenHeight - height) / 2 - rect.top;  
                } else if (rect.top > 0) {  
                    deltaY = -rect.top;  
                } else if (rect.bottom < screenHeight) {  
                    deltaY = this.getHeight() - rect.bottom;  
                }  
            }  
      
            if (horizontal) {  
                int screenWidth = dm.widthPixels;  
                if (width < screenWidth) {  
                    deltaX = (screenWidth - width) / 2 - rect.left;  
                } else if (rect.left > 0) {  
                    deltaX = -rect.left;  
                } else if (rect.right < screenWidth) {  
                    deltaX = screenWidth - rect.right;  
                }  
            }  
            matrix.postTranslate(deltaX, deltaY);  
        }  
          
        /**
         * 限制最大最小缩放比例,自动居中
         */  
        private void CheckView() {  
            float p[] = new float[9];  
            matrix.getValues(p);  
            if (mode == ZOOM) {  
                if (p[0] < minScaleR) {  
                    //Log.d("", "当前缩放级别:"+p[0]+",最小缩放级别:"+minScaleR);  
                    matrix.setScale(minScaleR, minScaleR);  
                }  
                if (p[0] > MAX_SCALE) {  
                    //Log.d("", "当前缩放级别:"+p[0]+",最大缩放级别:"+MAX_SCALE);  
                    matrix.set(savedMatrix);  
                }  
            }  
            center(true, true);  
        }  
          
        /**
         * 两点的距离
         */  
        private float spacing(MotionEvent event) {  
            float x = event.getX(0) - event.getX(1);  
            float y = event.getY(0) - event.getY(1);  
            return FloatMath.sqrt(x * x + y * y);  
        }  
        /**
         * 两点的中点
         */  
        private void midPoint(PointF point, MotionEvent event) {  
            float x = event.getX(0) + event.getX(1);  
            float y = event.getY(0) + event.getY(1);  
            point.set(x / 2, y / 2);  
        }  
    }

自定义ImageView的更多相关文章

  1. Android自定义ImageView实现图片圆形 ,椭圆和矩形圆角显示

    Android中的ImageView只能显示矩形的图片,为了用户体验更多,Android实现圆角矩形,圆形或者椭圆等图形,一般通过自定义ImageView来实现,首先获取到图片的Bitmap,然后通过 ...

  2. 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果

    首先呢,还是一贯作风,我们先来看看众多应用中的示例:(这种效果是很常见的,可以说应用的必须品.)                搜狐客户端                               ...

  3. (一)自定义ImageView,初步实现多点触控、自由缩放

    真心佩服那些一直专注于技术共享的大神们,正是因为他们无私的分享精神,我才能每天都有进步.近日又算是仔细学了android的自定义控件技术,跟着大神的脚步实现了一个自定义的ImageView.里面涉及到 ...

  4. android自定义控件(7)-获取自定义ImageView的src属性

    创建一个自定义组件,继承 ImageView.在我的 xml 布局文件中是这样设置的: <Mycomponent android:src="@drawable/my_test_imag ...

  5. Android -- 自定义ImageView(圆形头像)

    1.  原图

  6. 自定义ImageView回调实现手动改变圆环大小

    //-----------------自定义MyView继承Imageview------------------------------- package com.bw.yuanhuan; impo ...

  7. Android 自定义ImageView支持缩放,拖拽,方便复用

    今天刚发了一篇关于ImageView的缩放和拖拽的博客,然后我想了下,将他自定义下,方便我们来复用这个imageView,效果我就不多说了,http://blog.csdn.net/xiaanming ...

  8. Android自定义ImageView圆形头像

    效果图: 代码如下: RoundImageView.java import cn.comnav.evaluationsystem.R; import android.content.Context; ...

  9. 自定义ImageView的MainActivity

    package com.baidu.lianximyview; import com.example.myimageview.MyImageView; import android.os.Bundle ...

随机推荐

  1. codeblock报__objc_class_name_xxx问题

    添加来一个class文件,在其他文件调用时,报下面这个错误: undefined reference to `__objc_class_name_Test' 右击Test这个类的文件弹出Propert ...

  2. Asp.net_Webservice返回json

    [WebMethod] public List<PictureManager> LoadPictureOne() { dataDataContext context = new dataD ...

  3. AngularJS的directive(指令)配置选项说明

    js代码如下: var appModule = angular.module("appModule", []); appModule.controller("Ctrl&q ...

  4. 按键精灵 句柄 获得句柄 控制windows窗口 后台

    新建一个文本文档,打开,Windows就会给这个文本文档的窗口临时分配唯一的一串数字来标识这个窗体,以区别于其他窗口,这串数字就叫句柄.   因为句柄是临时随机分配的,所以每次虽然是打开同一个文件,但 ...

  5. java 多线程3(线程安全)

    需求:模拟三个窗口同时买票. 问题1:static 修饰num,只创建一份在内存中,要不就会创建3份. 问题2:线程安全问题.(代码重1的红色字体) 出现的原因:存在两个或两个以上的线程对象,而且线程 ...

  6. Android屏幕适配原理

    几个概念: 1) 屏幕密度(dpi) :dot per inch,即每英寸像素数. ldpi(120),mdpi(160),hdpi(240),xhdpi(320) 计算方法: 以480x854,4. ...

  7. Ubuntu安装nodeJS

    安装环境 ubuntu12.04 64bit nodejs-v0.8.14.tar.gz Node.js是一个基于google v8+javascript的服务端编程框架.但是Node.js又不是js ...

  8. GIS软件列表

    3map:行星地球项目由3map驱动,这是一个自由软件,由Telstra宽带基金会创建并支持,提供客户端与服务器的能力以在线再现虚拟地球. Amein!:其界面介于ArcMap和UMN Mapserv ...

  9. sh脚本异常:bad interpreter: No such file or directory

    转:http://bluedest.iteye.com/blog/1674963 在Linux中执行.sh脚本,异常/bin/sh^M: bad interpreter: No such file o ...

  10. uva--1339 - Ancient Cipher(模拟水体系列)

    1339 - Ancient Cipher Ancient Roman empire had a strong government system with various departments, ...