[6.7.0][Feat]切换高精地图和高德地图且带动画

This commit is contained in:
chenfufeng
2024-09-14 16:38:55 +08:00
parent 4eb3db6d37
commit 3d06ddb69e

View File

@@ -0,0 +1,282 @@
package com.mogo.eagle.core.function.hmi.map
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import androidx.constraintlayout.widget.ConstraintLayout
class ExchangeChildLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
private var mContext: Context? = null
private var isChange = false
private var isPlayingAnim = false
private var maxWidth = 0
private var maxHeight = 0
private var minWidth = 0
private var minHeight = 0
private var bottomX = 0f
private var bottomY = 0f
private var topX = 0f
private var topY = 0f
companion object {
private const val TAG = "ExchangeChildLayout"
private const val ANIM_DURATION = 600L
}
init {
try {
initView(context)
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun initView(context: Context) {
mContext = context
}
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
super.onWindowFocusChanged(hasWindowFocus)
if (hasWindowFocus) {
val bottomView = getChildAt(0)
val topView = getChildAt(childCount - 1)
maxWidth = bottomView.width
maxHeight = bottomView.height
minWidth = topView.width
minHeight = topView.height
bottomX = bottomView.x
bottomY = bottomView.y
topX = topView.x
topY = topView.y
}
}
/**
* 开启ViewGroup自定义绘制顺序
*/
fun setCustomOrder(enable: Boolean) {
isChildrenDrawingOrderEnabled = enable
}
/**
* 切换高精地图和高德地图View的位置
*/
fun exchange() {
if (!isPlayingAnim) {
isChange = !isChange
startAnim()
invalidate()
}
}
private fun startAnim() {
val bottomView = getChildAt(0)
val topView = getChildAt(childCount - 1)
val bottomXAnimator: ObjectAnimator
val bottomYAnimator: ObjectAnimator
val bottomWidthAnimator: ObjectAnimator
val bottomHeightAnimator: ObjectAnimator
val topXAnimator: ObjectAnimator
val topYAnimator: ObjectAnimator
val topWidthAnimator: ObjectAnimator
val topHeightAnimator: ObjectAnimator
if (isChange) {
exchangeRule(bottomView.layoutParams as LayoutParams, true, true)
bottomXAnimator = ObjectAnimator.ofFloat(bottomView, "x", bottomX, topX)
bottomYAnimator = ObjectAnimator.ofFloat(bottomView, "y", bottomY, topY)
bottomWidthAnimator =
ObjectAnimator.ofInt(
WrapperViewWidth(bottomView),
"width",
maxWidth,
minWidth
)
bottomHeightAnimator =
ObjectAnimator.ofInt(
WrapperViewHeight(bottomView),
"height",
maxHeight,
minHeight
)
exchangeRule(topView.layoutParams as LayoutParams, false, true)
topXAnimator = ObjectAnimator.ofFloat(topView, "x", topX, bottomX)
topYAnimator = ObjectAnimator.ofFloat(topView, "y", topY, bottomY)
topWidthAnimator =
ObjectAnimator.ofInt(
WrapperViewWidth(topView),
"width",
minWidth,
maxWidth
)
topHeightAnimator =
ObjectAnimator.ofInt(
WrapperViewHeight(topView),
"height",
minHeight,
maxHeight
)
} else {
exchangeRule(bottomView.layoutParams as LayoutParams, true, false)
bottomXAnimator = ObjectAnimator.ofFloat(bottomView, "x", topX, bottomX)
bottomYAnimator = ObjectAnimator.ofFloat(bottomView, "y", topY, bottomY)
bottomWidthAnimator =
ObjectAnimator.ofInt(
WrapperViewWidth(bottomView),
"width",
minWidth,
maxWidth
)
bottomHeightAnimator =
ObjectAnimator.ofInt(
WrapperViewHeight(bottomView),
"height",
minHeight,
maxHeight
)
exchangeRule(topView.layoutParams as LayoutParams, false, false)
topXAnimator = ObjectAnimator.ofFloat(topView, "x", bottomX, topX)
topYAnimator = ObjectAnimator.ofFloat(topView, "y", bottomY, topY)
topWidthAnimator =
ObjectAnimator.ofInt(
WrapperViewWidth(topView),
"width",
maxWidth,
minWidth
)
topHeightAnimator =
ObjectAnimator.ofInt(
WrapperViewHeight(topView),
"height",
maxHeight,
minHeight
)
}
// 将多个动画组合在一起
val animatorSet = AnimatorSet()
animatorSet.playTogether(
bottomXAnimator,
bottomYAnimator,
bottomWidthAnimator,
bottomHeightAnimator,
topXAnimator,
topYAnimator,
topWidthAnimator,
topHeightAnimator
)
animatorSet.addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator) {
isPlayingAnim = true
}
override fun onAnimationEnd(animation: Animator) {
isPlayingAnim = false
}
override fun onAnimationCancel(animation: Animator) {
isPlayingAnim = false
}
override fun onAnimationRepeat(animation: Animator) {
}
})
animatorSet.duration = ANIM_DURATION
animatorSet.interpolator = AccelerateDecelerateInterpolator()
// 启动动画
animatorSet.start()
}
fun getChangeFlag() = isChange
override fun isChildrenDrawingOrderEnabled() = super.isChildrenDrawingOrderEnabled()
override fun getChildDrawingOrder(childCount: Int, i: Int): Int {
return if (isChange) {
when (i) {
0 -> {
childCount - 1
}
childCount - 1 -> {
0
}
else -> {
i
}
}
} else {
super.getChildDrawingOrder(childCount, i)
}
}
// 用于包装 View 的宽度,以便可以使用 ObjectAnimator 来改变宽度
class WrapperViewWidth(
private val view: View,
) {
var width: Int
get() = view.layoutParams.width
set(width) {
val layoutParams = view.layoutParams as LayoutParams
layoutParams.width = width
view.layoutParams = layoutParams
}
}
class WrapperViewHeight(
private val view: View,
) {
var height: Int
get() = view.layoutParams.height
set(height) {
val layoutParams = view.layoutParams as LayoutParams
layoutParams.height = height
view.layoutParams = layoutParams
}
}
private fun exchangeRule(
layoutParams: LayoutParams, isBottom: Boolean,
isChange: Boolean
) {
if (isBottom) {
if (isChange) {
layoutParams.startToStart = LayoutParams.UNSET
layoutParams.topToTop = LayoutParams.UNSET
layoutParams.endToEnd = LayoutParams.PARENT_ID
layoutParams.bottomToBottom = LayoutParams.PARENT_ID
} else {
layoutParams.startToStart = LayoutParams.PARENT_ID
layoutParams.topToTop = LayoutParams.PARENT_ID
layoutParams.endToEnd = LayoutParams.UNSET
layoutParams.bottomToBottom = LayoutParams.UNSET
}
} else {
if (isChange) {
layoutParams.startToStart = LayoutParams.PARENT_ID
layoutParams.topToTop = LayoutParams.PARENT_ID
layoutParams.endToEnd = LayoutParams.UNSET
layoutParams.bottomToBottom = LayoutParams.UNSET
} else {
layoutParams.startToStart = LayoutParams.UNSET
layoutParams.topToTop = LayoutParams.UNSET
layoutParams.endToEnd = LayoutParams.PARENT_ID
layoutParams.bottomToBottom = LayoutParams.PARENT_ID
}
}
}
}