diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/map/ExchangeChildLayout.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/map/ExchangeChildLayout.kt new file mode 100644 index 0000000000..6daa544d86 --- /dev/null +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/map/ExchangeChildLayout.kt @@ -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 + } + } + } +} \ No newline at end of file