Android预览超长图原图并且可以滑动查看超长图

概述:
  根据需求方的要求,app中预览大图需要显示高清图片。且支持高清预览横向长图(原图)和纵向长图(原图)。且图片可以自由的放大缩小,并且超长图默认需要撑满横屏或者竖屏,可以滑动查看被遮挡的部分
  项目中使用Glide来加载图片,默认情况下Glide是不显示原图的,并且会根据ScaleType计算缓存图片大小然后显示出来。
  显示原图可行的方案有两种:
    1.通过Glide的asDrawable或者asBitmap把实际的drawable或者Bitmap取出来并放到对应的View上。
    2.通过设置Glide.with(this).override(原始图片宽度,原始图片高度)
  预览超长图:
    1.使用ScalePhotoView

示例代码(重在思路):

1.预览的工具类(支持本地图片和网络图片预览)

class ScaleLongImageUtil {
    private fun tooHeight(path: String, photoView: GalleryScalePhotoView) {
        GlideUtils.getInstance()
            .loadNetDrawable(path, photoView, object : GlideUtils.OnDrawableLoadedListener {
                override fun onLoadSuccess(resource: Drawable?) {
                    photoView.setImageDrawable(resource)
                    scaleImageVPolicy(photoView, resource!!)
                }

                override fun onLoadFailed() {

                }
            })
    }

    /**
     * 竖长图缩放策略:
     * 1.默认宽度缩放至屏幕宽度
     * 2.双击:如果缩放系数>1.0f就=1.0f,如果<=1.0f就放大两倍
     */
    private fun scaleImageVPolicy(
        photoView: GalleryScalePhotoView,
        drawable: Drawable
    ) {
        var scale = 1f
        var orgScale = 1f
        getRealData(photoView) { realWidth, realHeight ->
            val screenWidth = PxUtils.getScreenWidth(photoView.context)
            scale = screenWidth / (realWidth * 1.0f)
            orgScale = scale
            photoView.setScale(scale, true)
            LogUtils.e("width:$realWidth,height:$realHeight,scale:$scale,screenWidth:$screenWidth")
        }
        photoView.setOnDoubleTapListener(object : GestureDetector.OnDoubleTapListener {
            override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
                return true
            }

            override fun onDoubleTap(e: MotionEvent?): Boolean {
                var currentScale = photoView.scale
                if (orgScale >= currentScale) {
                    photoView.scale = scale * 2
                } else {
                    photoView.scale = orgScale
                }
                return true
            }

            override fun onDoubleTapEvent(e: MotionEvent?): Boolean {
                return true
            }

        })
    }

    /**
     * 横向图片的缩放策略
     * 1.默认显示完整宽度(不做任何处理就行,因为fitCenter模式就能完美完成)
     * 2.放大后双击恢复缩小显示
     * 3.如果是缩小装填双击放大置最高等
     */
    private fun scaleImageHPolicy(photoView: GalleryScalePhotoView) {
        photoView.setOnDoubleTapListener(object : GestureDetector.OnDoubleTapListener {
            override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
                return true
            }

            override fun onDoubleTap(e: MotionEvent?): Boolean {
                var currentScale = photoView.scale
                if (currentScale > 1.0f) {
                    photoView.scale = 1.0f
                } else {
                    photoView.scale = 20.0f
                }
                return true
            }

            override fun onDoubleTapEvent(e: MotionEvent?): Boolean {
                return true
            }

        })
    }

    private fun imageTooWidth(photoView: GalleryScalePhotoView) {
        scaleImageHPolicy(photoView)
    }

    /**
     * 定义长图和宽图的策略
     */
    fun showImageWHPolicy(
        path: String,
        photoView: GalleryScalePhotoView,
        imageWidth: Int,
        imageHeight: Int
    ) {
        LongImageUtil.scaleLongImage(
            photoView.context,
            imageWidth,
            imageHeight,
            object : LongImageUtil.OnImageScaleListener {
                override fun onTooWidth(scale: Float) {
                    LogUtils.e("方法名:onTooWidth")
                    GlideUtils.getInstance().loadNetImage(path, photoView)
                    imageTooWidth(photoView)
                }

                override fun onTooHeight(scale: Float) {
                    LogUtils.e("方法名:onTooHeight")
                    tooHeight(path, photoView)
                }

                override fun onNormal() {
                    LogUtils.e("方法名:onNormal")
                    //啥也不用干
                    //不对,应该有一个正常图片的双击策略
                    GlideUtils.getInstance().loadNetImage(path, photoView)
                }

            },
            PxUtils.getScreenWidth(photoView.context),
            PxUtils.dp2px(photoView.context, 235f)
        )
    }

    /**
     * 获取ImageView实际图片的宽高
     */
    private fun getRealData(
        photoView: GalleryScalePhotoView,
        getWH: (relWidth: Int, relHeight: Int) -> Unit
    ) {
        // 获取图片大小        在onDraw()内才能拿到值
        val width: Int = photoView.drawable.bounds.width()
        val height: Int = photoView.drawable.bounds.height()
        //获得ImageView中Image的变换矩阵
        val m: Matrix = photoView.imageMatrix
        val values = FloatArray(10)
        m.getValues(values)
        //Image在绘制过程中的变换矩阵,从中获得x和y方向的缩放系数
        val sx = values[0]
        val sy = values[4]
        val realImgShowWidth = (width * sx).toInt()
        val realImgShowHeight = (height * sy).toInt()
        LogUtils.e("realImgShowWidth:${realImgShowWidth},realImgShowHeight:${realImgShowHeight}")
        getWH(realImgShowWidth, realImgShowHeight)
    }
}

2.使用方法

 scaleUtil = ScaleLongImageUtil()
 scaleUtil?.showImageWHPolicy(url, ivScaleView, 图片原始宽度, 图片原始高度)

ps:有一个地方非常重要,那就是当ImageView设置ScaleType.fitCenter的时候如何拿到ImageView中的显示区域实际的宽高。拿到这个宽高后就可以就按scale的值了

/**
     * 获取ImageView实际图片的宽高
     */
    private fun getRealData(
        photoView: GalleryScalePhotoView,
        getWH: (relWidth: Int, relHeight: Int) -> Unit
    ) {
        // 获取图片大小        在onDraw()内才能拿到值
        val width: Int = photoView.drawable.bounds.width()
        val height: Int = photoView.drawable.bounds.height()
        //获得ImageView中Image的变换矩阵
        val m: Matrix = photoView.imageMatrix
        val values = FloatArray(10)
        m.getValues(values)
        //Image在绘制过程中的变换矩阵,从中获得x和y方向的缩放系数
        val sx = values[0]
        val sy = values[4]
        val realImgShowWidth = (width * sx).toInt()
        val realImgShowHeight = (height * sy).toInt()
        LogUtils.e("realImgShowWidth:${realImgShowWidth},realImgShowHeight:${realImgShowHeight}")
        getWH(realImgShowWidth, realImgShowHeight)
    }

 

posted on 2023-02-22 19:07  飘杨......  阅读(500)  评论(0编辑  收藏  举报