仿微信图片浏览时拖动缩放的效果,布局封装
package com.chenbin.scenetransition
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.app.Activity
import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
/**
* @Description
* @Author elden
* @Date 2023/9/11 14:36
*/
class DragLayout : FrameLayout {
val TAG = DragLayout::class.java.simpleName
constructor(context: Context) : super(context)
constructor(context: Context, attr: AttributeSet) : super(context, attr)
companion object {
const val maxGoBackHeight = 400 //滑动多少Y后还能回弹回原位
const val minDragOpenLength = 40 //触发拖动的滑动距离
}
var onShareChangedListener: OnShareChangedListener? = null
private var mDragListener: OnDragDistanceListener? = null
var onDragDistanceListener: OnDragDistanceListener? = null
var dragView: View = this
private var downX = 0f
private var downY = 0f
private var sourceX = 0f
private var sourceY = 0f
private var openDrag = false //是否开启拖动
private var isAnim = false //是否在动画中
private val animatorSet = AnimatorSet()
init {
mDragListener = object : OnDragDistanceListener {
override fun onDrag(distance: Float) {
onDragDistanceListener?.onDrag(distance)
//缩放
val ratio = 1 - distance / maxGoBackHeight / 8
dragView.scaleX = ratio
dragView.scaleY = ratio
}
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
downX = event.rawX
downY = event.rawY
sourceX = event.rawX
sourceY = event.rawY
Log.e(TAG, "ACTION_DOWN sourceX = $sourceX , sourceY = $sourceY")
}
MotionEvent.ACTION_MOVE -> {
Log.e(TAG, "ACTION_MOVE event.rawY = ${event.rawY}, downY = $downY")
if (event.rawY - minDragOpenLength > downY && !isAnim) {
openDrag = true
}
if (openDrag) {
animatorSet.cancel()
dragView.translationX += event.rawX - sourceX
dragView.translationY += event.rawY - sourceY
Log.e(TAG, "移动 event.rawX = ${event.rawX} , event.rawY = ${event.rawY}")
sourceX = event.rawX
sourceY = event.rawY
mDragListener?.onDrag(Math.abs(dragView.translationY))
return true
}
}
MotionEvent.ACTION_UP -> {
Log.e(TAG, "ACTION_UP")
openDrag = false
gotoSourcePosition()
}
}
return true
// return super.onTouchEvent(event)
}
//回归原位
private fun gotoSourcePosition() {
if (dragView.translationY > maxGoBackHeight) {
if (context is Activity) {
animatorSet.cancel()
(context as Activity).onBackPressed()
}
return
}
val xAnim = ObjectAnimator.ofFloat(dragView, "translationX", dragView.translationX, 0f)
val yAnim = ObjectAnimator.ofFloat(dragView, "translationY", dragView.translationY, 0f)
yAnim.addUpdateListener {
mDragListener?.onDrag(Math.abs(it.animatedValue as Float))
}
// animatorSet.addListener(object : Animator.AnimatorListener {
// override fun onAnimationStart(animation: Animator) {
// isAnim = true
// }
//
// override fun onAnimationEnd(animation: Animator) {
// isAnim = false
// }
//
// override fun onAnimationCancel(animation: Animator) {
// isAnim = false
// }
//
// override fun onAnimationRepeat(animation: Animator) {
// isAnim = true
// }
// })
animatorSet.playTogether(xAnim, yAnim)
animatorSet.start()
}
var isFirstLayout = true
var firstLayoutRect = Rect()
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
if (isFirstLayout) {
isFirstLayout = false
getDrawingRect(firstLayoutRect)
}
dragView = getChildAt(0)
}
interface OnDragDistanceListener {
fun onDrag(distance: Float)
}
interface OnShareChangedListener {
fun onChanged(position: Int)
}
}