android 自定義控件實現圖片縮放

2024-02-16 05:18

本文主要是介绍android 自定義控件實現圖片縮放,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

public class MyImageView extends ImageView implements View.OnTouchListener
{

        public interface ImageViewVisiable
        {

              // 其他控件隱藏域顯示囘調函數
                public void visiable(int flag);
        }
        
        private ImageViewVisiable mImageViewVisiable;
        
        public void setImageViewVisiable(ImageViewVisiable imageViewVisiable)
        {
                 this.mImageViewVisiable = imageViewVisiable;
        }
        
        /**
         * 变换图片的矩阵
         */
        private Matrix matrix;

        /**
         * 记录图片矩阵状态
         */
        private Matrix saveMatrix;

        /**
         * 起始触摸点
         */
        private PointF start;

        /**
         * 触摸状态
         */
        public int MODE = MODE_INIT;

        /**
         * 初始状态,点击后隐藏标题、评论等
         */
        public static final int MODE_INIT = 1;

        /**
         * 图片为初始大小的满屏状态,未缩放,点击后显现标题、评论等
         */
        public static final int MODE_FULLSCREEN = 2;

        /**
         * 缩放状态
         */
        public static final int MODE_ZOOM = 3;

        /**
         * 拖拽状态
         */
        public static final int MODE_DRAG = 4;

        private float oldDistance;

        private float newDistance;

        private PointF midPoint;

        /**
         * 这一次手指移动后产生的缩放比例,初始是1
         */
        private float scale = 1;

        /**
         * 之前保存的缩放比例,初始是1
         */
        private float savedScale = 1;

        /**
         * 组件
         */
        
        private int mWidth;
        
        private int mHeight;
        
        private Context context;
        
        float left;
        float top;
        float right;
        float bottom;
        
        /** <默认构造函数>
         */
        public MyImageView(Context context) {
                super(context);
                init(context);
        }
        
        /** <默认构造函数>
         */
        public MyImageView(Context context,AttributeSet attrs) {
                super(context,attrs);
                init(context);
        }
        
        private void init(Context context)
        {
                this.mWidth = 400;
                this.mHeight = 400;
                this.context = context;
                matrix = new Matrix();
                saveMatrix = new Matrix();
                start = new PointF();
                midPoint = new PointF();
                setOnTouchListener(this);
        }

        private boolean getImageInfo(ImageView view)
    {
        Drawable mDrawable = null;
        if (view != null)
        {
           mDrawable =  view.getDrawable();
           if (mDrawable != null)
           {
               Rect rect = mDrawable.getBounds(); 
               float[] values = new float[9]; 
               matrix.getValues(values); 
                left = values[2];
               top = values[5];
               right = left + rect.width() * values[0];
               bottom = top + rect.height() * values[0];
           }
        }
        if (mDrawable == null)
        {
                LogUtil.d("獲取圖片失敗,請檢查是否因為內存吃緊,圖片被回收");
            return false;
        }
        return true;
    }
        
        
        public void postTranslate(MotionEvent event, ImageView view)
    {
        getImageInfo(view);
        LogUtil.d("Move获取当前图片的left:" + left + "|top:" +top + "|right:" + right + "|bottom:" + bottom);
        matrix.set(saveMatrix);

        float translateX = (event.getX() - start.x);
        float translateY = (event.getY() - start.y);
        LogUtil.d("把图片平移至:" + translateX + "x" + translateY);
        matrix.postTranslate(translateX,translateY);
    }
        
        public void stopOutScreen()
    {
        float translateX = 0;
        float translateY = 0;
        if (right > mWidth && left < 0)
        {
        }
        else
        {
            //往左
            if (right < mWidth) //当图片宽度已经大于屏幕
            {
                translateX = mWidth - right  ;
            }
            else if (left > 0)
            {
                translateX =0 - left;
            }

        }
        if (top < 0 && bottom > mHeight)
        {
        }
        else
        {
          //往上滑动
            if (top <0)
            {
                translateY =  0 - top;
            }
            else if (bottom > mHeight)
            {
                translateY = mHeight -bottom;
            }
        }
        LogUtil.d("图片还原至:" + translateX + "x" + translateY);
        matrix.postTranslate(translateX,translateY);
    }
        
        public void setPoint(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);

        }
        
        /**
         * 获取2个触控点距离
         * 
         * @param event
         * @return
         */
        public float caculateDistance(MotionEvent event)
        {
                float x = 0;
                float y = 0;
                try{
                        x = event.getX(0) - event.getX(1);
                        y = event.getY(0) - event.getY(1);
                }catch(IllegalArgumentException e){
                }
                return FloatMath.sqrt(x * x + y * y);
        }

        public void actionDown(ImageView v, MotionEvent event)
        {
                LogUtil.d("ACTION_DOWN  " + MODE);
                matrix.set(v.getImageMatrix());
                saveMatrix.set(matrix);
                // 得到当前点的位置
                start.set(event.getX(), event.getY());
                // 拖动
                if (savedScale > 1)
                {
                        MODE = MODE_DRAG;
                }
                getImageInfo(v);
                v.setImageMatrix(matrix);
        }
        
        public void actionMove(ImageView v, MotionEvent event)
        {
                // 拖动
                if (MODE == MODE_DRAG) {
                        postTranslate(event, v);
                }
                // 缩放
                else if (MODE == MODE_ZOOM) {

                        newDistance = caculateDistance(event);
                        if (newDistance > 5f) {
                                matrix.set(saveMatrix);
                                scale = newDistance / oldDistance;
                                matrix.postScale(scale, scale, midPoint.x, midPoint.y);
                        }
                }
                v.setImageMatrix(matrix);
        }
        
        public void actionPointerDown(ImageView v, MotionEvent event)
        {
                LogUtil.d("ACTION_POINTER_DOWN  " + MODE);
                if (MODE == MODE_FULLSCREEN || MODE == MODE_DRAG)
                {
                        oldDistance = caculateDistance(event);
                        v.setScaleType(ScaleType.MATRIX);
                        if (oldDistance > 10f)
                        {
                                saveMatrix.set(matrix);
                                setPoint(midPoint, event);
                                MODE = MODE_ZOOM;
                        }
                }
                v.setImageMatrix(matrix);
        }
        
        public void actionPointerUp(ImageView v, MotionEvent event)
        {
                LogUtil.d("ACTION_POINTER_UP  " + MODE);
        }
        
        
        public void actionUp(MotionEvent enent)
        {
                LogUtil.d("ACTION_UP  " + MODE);
                // 隐藏标题、评论
                if (MODE == MODE_INIT)
                {
                        MODE = MODE_FULLSCREEN;
                         mImageViewVisiable.visiable(GONE);
                }
                // 显示标题、评论
                else if (MODE == MODE_FULLSCREEN)
                {
                        mImageViewVisiable.visiable(VISIBLE);
                        MODE = MODE_INIT;
                }
                // 缩放
                else if (MODE == MODE_ZOOM)
                {
                        savedScale *= scale;
                        if (savedScale > 2)
                        {
                                setScaleType(ScaleType.FIT_CENTER);
                                savedScale = 1;
                                scale = 1;
                                MODE = MODE_FULLSCREEN;
                        } else if (savedScale < 1)
                        {
                                setScaleType(ScaleType.FIT_CENTER);
                                savedScale = 1;
                                scale = 1;
                                MODE = MODE_FULLSCREEN;
                        } else if (savedScale == 1)
                        {
                                MODE = MODE_FULLSCREEN;
                        }
                        
                }
                else if (MODE == MODE_DRAG)
                {
                    stopOutScreen();
                }
                setImageMatrix(matrix);
        }

        @Override
        public boolean onTouch(View v, MotionEvent event) 
        {
                ImageView view = (ImageView) v;
                switch (event.getAction() & MotionEvent.ACTION_MASK)
                {
                case MotionEvent.ACTION_DOWN:
                        
                        actionDown(view, event);
                        break;
                case MotionEvent.ACTION_MOVE:
                        
                        actionMove(view, event);
                        break;
                case MotionEvent.ACTION_POINTER_DOWN:
                        
                        actionPointerDown(view, event);
                        break;
                case MotionEvent.ACTION_POINTER_UP:
                        
                        actionPointerUp(view, event);
                        break;
                case MotionEvent.ACTION_UP:
                        
                        actionUp(event);
                        break;
                }
                return true;
        }
        
}

这篇关于android 自定義控件實現圖片縮放的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/713595

相关文章

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

WinForms中主要控件的详细使用教程

《WinForms中主要控件的详细使用教程》WinForms(WindowsForms)是Microsoft提供的用于构建Windows桌面应用程序的框架,它提供了丰富的控件集合,可以满足各种UI设计... 目录一、基础控件1. Button (按钮)2. Label (标签)3. TextBox (文本框

Android NDK版本迭代与FFmpeg交叉编译完全指南

《AndroidNDK版本迭代与FFmpeg交叉编译完全指南》在Android开发中,使用NDK进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时,本文将深入分析A... 目录一、android NDK版本迭代分界线二、FFmpeg交叉编译关键注意事项三、完整编译脚本示例四

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

Android 实现一个隐私弹窗功能

《Android实现一个隐私弹窗功能》:本文主要介绍Android实现一个隐私弹窗功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 效果图如下:1. 设置同意、退出、点击用户协议、点击隐私协议的函数参数2. 《用户协议》、《隐私政策》设置成可点击的,且颜色要区分出来res/l

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja

Android开发环境配置避坑指南

《Android开发环境配置避坑指南》本文主要介绍了Android开发环境配置过程中遇到的问题及解决方案,包括VPN注意事项、工具版本统一、Gerrit邮箱配置、Git拉取和提交代码、MergevsR... 目录网络环境:VPN 注意事项工具版本统一:android Studio & JDKGerrit的邮