概述:
根据需求方的要求,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)
}