Android 双击缩放使图像向图像中心缩放
目前,我已经实现了一个自定义类,该类实现了AppCompatImageView、OnGetureListener和OnDoubleTapListener,以构建我自己的ImageView,在本文的帮助下,该ImageView可以通过收缩来放大或缩小 这里我缺少的是,当用户双击图像的一角时,默认情况下图像会向图像的中心缩放。如何确保双击时考虑到点击坐标以缩放到该坐标 这是我的TouchImageView课程Android 双击缩放使图像向图像中心缩放,android,android-layout,kotlin,pinchzoom,Android,Android Layout,Kotlin,Pinchzoom,目前,我已经实现了一个自定义类,该类实现了AppCompatImageView、OnGetureListener和OnDoubleTapListener,以构建我自己的ImageView,在本文的帮助下,该ImageView可以通过收缩来放大或缩小 这里我缺少的是,当用户双击图像的一角时,默认情况下图像会向图像的中心缩放。如何确保双击时考虑到点击坐标以缩放到该坐标 这是我的TouchImageView课程 class TouchImageView : androidx.appcompat.wid
class TouchImageView : androidx.appcompat.widget.AppCompatImageView, GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {
var matrix1: Matrix? = null
var mode = NONE
// Remember some things for zooming
var last = PointF()
var start = PointF()
var minScale = 1f
var maxScale = 3f
var m: FloatArray? = null
var viewWidth = 0
var viewHeight = 0
var saveScale = 1f
protected var origWidth = 0f
protected var origHeight = 0f
var oldMeasuredWidth = 0
var oldMeasuredHeight = 0
var mScaleDetector: ScaleGestureDetector? = null
// var context: Context? = null
var context1 : Context? = null
constructor(context: Context) : super(context) {
sharedConstructing(context)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
sharedConstructing(context)
}
var mGestureDetector: GestureDetector? = null
private fun sharedConstructing(context: Context) {
super.setClickable(true)
this.context1 = context
mGestureDetector = GestureDetector(context, this)
mGestureDetector!!.setOnDoubleTapListener(this)
mScaleDetector = ScaleGestureDetector(context, ScaleListener())
matrix1 = Matrix()
m = FloatArray(9)
imageMatrix = matrix1
scaleType = ScaleType.MATRIX
setOnTouchListener { v, event ->
mScaleDetector!!.onTouchEvent(event)
mGestureDetector!!.onTouchEvent(event)
val curr = PointF(event.x, event.y)
when (event.action) {
MotionEvent.ACTION_DOWN -> {
last.set(curr)
start.set(last)
mode = DRAG
}
MotionEvent.ACTION_MOVE -> if (mode == DRAG) {
val deltaX = curr.x - last.x
val deltaY = curr.y - last.y
val fixTransX = getFixDragTrans(
deltaX, viewWidth.toFloat(),
origWidth * saveScale
)
val fixTransY = getFixDragTrans(
deltaY, viewHeight.toFloat(),
origHeight * saveScale
)
matrix1!!.postTranslate(fixTransX, fixTransY)
fixTrans()
last[curr.x] = curr.y
}
MotionEvent.ACTION_UP -> {
mode = NONE
val xDiff = Math.abs(curr.x - start.x).toInt()
val yDiff = Math.abs(curr.y - start.y).toInt()
if (xDiff < CLICK && yDiff < CLICK) performClick()
}
MotionEvent.ACTION_POINTER_UP -> mode = NONE
}
imageMatrix = matrix1
invalidate()
true // indicate event was handled
}
}
fun setMaxZoom(x: Float) {
maxScale = x
}
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
return false
}
override fun onDoubleTap(e: MotionEvent): Boolean {
// Double tap is detected
Log.i("MAIN_TAG", "Double tap detected")
val origScale = saveScale
val mScaleFactor: Float
if (saveScale == maxScale) {
saveScale = minScale
mScaleFactor = minScale / origScale
} else {
saveScale = maxScale
mScaleFactor = maxScale / origScale
}
matrix1!!.postScale(
mScaleFactor, mScaleFactor, (viewWidth / 2).toFloat(), (
viewHeight / 2).toFloat()
)
fixTrans()
return false
}
override fun onDoubleTapEvent(e: MotionEvent): Boolean {
return false
}
override fun onDown(e: MotionEvent): Boolean {
return false
}
override fun onShowPress(e: MotionEvent) {}
override fun onSingleTapUp(e: MotionEvent): Boolean {
return false
}
override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
return false
}
override fun onLongPress(e: MotionEvent) {}
override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
return false
}
private inner class ScaleListener : SimpleOnScaleGestureListener() {
override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
mode = ZOOM
return true
}
override fun onScale(detector: ScaleGestureDetector): Boolean {
var mScaleFactor = detector.scaleFactor
val origScale = saveScale
saveScale *= mScaleFactor
if (saveScale > maxScale) {
saveScale = maxScale
mScaleFactor = maxScale / origScale
} else if (saveScale < minScale) {
saveScale = minScale
mScaleFactor = minScale / origScale
}
if (origWidth * saveScale <= viewWidth
|| origHeight * saveScale <= viewHeight
) matrix1!!.postScale(
mScaleFactor, mScaleFactor, (viewWidth / 2).toFloat(), (
viewHeight / 2).toFloat()
) else matrix1!!.postScale(
mScaleFactor, mScaleFactor,
detector.focusX, detector.focusY
)
fixTrans()
return true
}
}
fun fixTrans() {
matrix1!!.getValues(m)
val transX = m!![Matrix.MTRANS_X]
val transY = m!![Matrix.MTRANS_Y]
val fixTransX = getFixTrans(transX, viewWidth.toFloat(), origWidth * saveScale)
val fixTransY = getFixTrans(
transY, viewHeight.toFloat(), origHeight
* saveScale
)
if (fixTransX != 0f || fixTransY != 0f) matrix1!!.postTranslate(fixTransX, fixTransY)
}
fun getFixTrans(trans: Float, viewSize: Float, contentSize: Float): Float {
val minTrans: Float
val maxTrans: Float
if (contentSize <= viewSize) {
minTrans = 0f
maxTrans = viewSize - contentSize
} else {
minTrans = viewSize - contentSize
maxTrans = 0f
}
if (trans < minTrans) return -trans + minTrans
return if (trans > maxTrans) -trans + maxTrans else 0f
}
private fun getFixDragTrans(delta: Float, viewSize: Float, contentSize: Float): Float {
return if (contentSize <= viewSize) {
0f
} else delta
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
viewWidth = MeasureSpec.getSize(widthMeasureSpec)
viewHeight = MeasureSpec.getSize(heightMeasureSpec)
//
// Rescales image on rotation
//
if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight || viewWidth == 0 || viewHeight == 0) return
oldMeasuredHeight = viewHeight
oldMeasuredWidth = viewWidth
if (saveScale == 1f) {
// Fit to screen.
val scale: Float
val drawable = drawable
if (drawable == null || drawable.intrinsicWidth == 0 || drawable.intrinsicHeight == 0) return
val bmWidth = drawable.intrinsicWidth
val bmHeight = drawable.intrinsicHeight
Log.d("bmSize", "bmWidth: $bmWidth bmHeight : $bmHeight")
val scaleX = viewWidth.toFloat() / bmWidth.toFloat()
val scaleY = viewHeight.toFloat() / bmHeight.toFloat()
scale = Math.min(scaleX, scaleY)
matrix1!!.setScale(scale, scale)
// Center the image
var redundantYSpace = (viewHeight.toFloat()
- scale * bmHeight.toFloat())
var redundantXSpace = (viewWidth.toFloat()
- scale * bmWidth.toFloat())
redundantYSpace /= 2.toFloat()
redundantXSpace /= 2.toFloat()
matrix1!!.postTranslate(redundantXSpace, redundantYSpace)
origWidth = viewWidth - 2 * redundantXSpace
origHeight = viewHeight - 2 * redundantYSpace
imageMatrix = matrix1
}
fixTrans()
}
companion object {
// We can be in one of these 3 states
const val NONE = 0
const val DRAG = 1
const val ZOOM = 2
const val CLICK = 3
}
class TouchImageView:androidx.appcompat.widget.AppCompatImageView、GestureDetector.OnGetureListener、GestureDetector.OnDoubleTapListener{
var matrix1:矩阵?=null
var模式=无
//记住一些关于缩放的事情
var last=PointF()
var start=PointF()
var minScale=1f
var maxScale=3f
变量m:FloatArray?=null
var viewWidth=0
var viewHeight=0
var saveScale=1f
受保护变量origWidth=0f
受保护的var origHeight=0f
var oldMeasuredWidth=0
var oldMeasuredHeight=0
var mScaleDetector:ScaleGetStureDetector?=null
//变量上下文:上下文?=null
var context1:上下文?=null
构造函数(上下文:上下文):超级(上下文){
共享构造(上下文)
}
构造函数(context:context,attrs:AttributeSet?):super(context,attrs){
共享构造(上下文)
}
var mGestureDetector:GestureDetector?=null
私有趣味共享构造(上下文:上下文){
super.setClickable(真)
this.context1=context
mGestureDetector=GestureDetector(上下文,此)
mGestureDetector!!.setOnDoubleTapListener(此)
mScaleDetector=scalegestruedetector(上下文,ScaleListener())
矩阵1=矩阵()
m=浮点数组(9)
imageMatrix=matrix1
scaleType=scaleType.MATRIX
setOnTouchListener{v,事件->
mScaleDetector!!.onTouchEvent(事件)
mGestureDetector!!.onTouchEvent(事件)
val curr=PointF(event.x,event.y)
何时(事件、动作){
MotionEvent.ACTION\u向下->{
最后一组(当前)
开始。设置(最后一个)
模式=拖动
}
MotionEvent.ACTION\u MOVE->if(模式==拖动){
val deltaX=当前x-最后x
val deltaY=当前y-最后y
val fixtranx=getfixtragtrans(
deltaX,viewWidth.toFloat(),
原始宽度*保存比例
)
val fixTransY=getfixtragtrans(
deltaY,viewHeight.toFloat(),
origHeight*保存比例
)
matrix1!!.postTranslate(fixtranx,fixtrany)
fixTrans()
最后一次[当前x]=当前
}
MotionEvent.ACTION\u UP->{
模式=无
val xDiff=Math.abs(curr.x-start.x).toInt()
val yDiff=Math.abs(curr.y-start.y).toInt()
if(xDiff模式=无
}
imageMatrix=matrix1
使无效
true//指示事件已处理
}
}
fun setMaxZoom(x:Float){
最大刻度=x
}
override fun OnSingleTapConfiged(e:MotionEvent):布尔值{
返回错误
}
override fun onDoubleTap(e:MotionEvent):布尔值{
//检测到双抽头
Log.i(“主标签”,“检测到双击”)
val origScale=saveScale
val mScaleFactor:浮点
如果(saveScale==maxScale){
saveScale=minScale
mScaleFactor=最小刻度/原始刻度
}否则{
saveScale=maxScale
mScaleFactor=最大刻度/原始刻度
}
matrix1!!.postScale(
mScaleFactor,mScaleFactor,(viewWidth/2).toFloat()(
viewHeight/2).toFloat()
)
fixTrans()
返回错误
}
重写DoubleTapeEvent(e:MotionEvent):布尔值{
返回错误
}
override fun onDown(e:MotionEvent):布尔值{
返回错误
}
在ShowPress(e:MotionEvent){}
override fun onSingleTapUp(e:MotionEvent):布尔值{
返回错误
}
覆盖趣味onScroll(e1:MotionEvent,e2:MotionEvent,distanceX:Float,distanceY:Float):布尔值{
返回错误
}
重写fun onLongPress(e:MotionEvent){}
重写fun onFling(e1:MotionEvent,e2:MotionEvent,velocityX:Float,velocityY:Float):布尔值{
返回错误
}
私有内部类ScaleListener:SimpleOnScaleGetStureListener(){
覆盖SCALEBEGIN(检测器:SCALEGSTUREDETECTOR):布尔值{
模式=缩放
返回真值
}
在刻度上覆盖乐趣(检测器:scalegestruedetector):布尔值{
var mScaleFactor=detector.scaleFactor
val origScale=saveScale
saveScale*=mScaleFactor
如果(保存比例>最大比例){
saveScale=maxScale
mScaleFactor=最大刻度/原始刻度
}else if(保存比例<最小比例){
saveScale=minScale
mScaleFactor=最小刻度/原始刻度
}
如果(origWidth*saveScale您尝试过吗
我可以想象它具有您所需的所有功能,并且维护良好谢谢此库在我的应用程序中运行良好