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
index 6daa544d86..9f461f9006 100644
--- 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
@@ -1,14 +1,23 @@
package com.mogo.eagle.core.function.hmi.map
import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
+import android.animation.PropertyValuesHolder
import android.content.Context
import android.util.AttributeSet
import android.view.View
-import android.view.animation.AccelerateDecelerateInterpolator
import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.ConstraintSet
+import com.mogo.eagle.core.function.hmi.R
+import com.mogo.eagle.core.function.hmi.util.ConstraintUtil
+import kotlinx.android.synthetic.main.view_map_container.view.exchangeLayout
+import me.jessyan.autosize.utils.AutoSizeUtils
+/**
+ * 可自定义绘制顺序的ConstraintLayout
+ */
class ExchangeChildLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@@ -16,8 +25,6 @@ class ExchangeChildLayout @JvmOverloads constructor(
) : 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
@@ -27,11 +34,16 @@ class ExchangeChildLayout @JvmOverloads constructor(
private var bottomY = 0f
private var topX = 0f
private var topY = 0f
+ private var bScaleX = 0f
+ private var bScaleY = 0f
+ private var tScaleX = 0f
+ private var tScaleY = 0f
- companion object {
- private const val TAG = "ExchangeChildLayout"
- private const val ANIM_DURATION = 600L
- }
+ private var isSwapped = false
+ private var isPlayingAnim = false
+
+ private var animatorSet: AnimatorSet? = null
+ private var constraintUtil: ConstraintUtil? = null
init {
try {
@@ -41,19 +53,53 @@ class ExchangeChildLayout @JvmOverloads constructor(
}
}
+ companion object {
+ private const val ANIM_DURATION = 500L
+ }
+
private fun initView(context: Context) {
mContext = context
+ isChildrenDrawingOrderEnabled = true
}
+ /**
+ * 开启ViewGroup自定义绘制顺序
+ */
+ fun setSwapped(isSwapped: Boolean) {
+ if (!isPlayingAnim) {
+ this.isSwapped = isSwapped
+ invalidate()
+ }
+ }
+
+ fun swapViews() {
+ if (!isPlayingAnim) {
+ isSwapped = !isSwapped
+ startAnim()
+ }
+ }
+
+ fun getSwapFlag() = isSwapped
+
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
super.onWindowFocusChanged(hasWindowFocus)
if (hasWindowFocus) {
+ calculate()
+ }
+ }
+
+ private fun calculate() {
+ if (maxWidth == 0 && maxHeight == 0) {
val bottomView = getChildAt(0)
val topView = getChildAt(childCount - 1)
maxWidth = bottomView.width
maxHeight = bottomView.height
minWidth = topView.width
minHeight = topView.height
+ bScaleX = (topView.width.toDouble() / bottomView.width.toDouble()).toFloat()
+ bScaleY = (topView.height.toDouble() / bottomView.height.toDouble()).toFloat()
+ tScaleX = (bottomView.width.toDouble() / topView.width.toDouble()).toFloat()
+ tScaleY = (bottomView.height.toDouble() / topView.height.toDouble()).toFloat()
bottomX = bottomView.x
bottomY = bottomView.y
topX = topView.x
@@ -61,150 +107,101 @@ class ExchangeChildLayout @JvmOverloads constructor(
}
}
- /**
- * 开启ViewGroup自定义绘制顺序
- */
- fun setCustomOrder(enable: Boolean) {
- isChildrenDrawingOrderEnabled = enable
- }
-
- /**
- * 切换高精地图和高德地图View的位置
- */
- fun exchange() {
- if (!isPlayingAnim) {
- isChange = !isChange
- startAnim()
- invalidate()
- }
- }
-
private fun startAnim() {
+ calculate()
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
+ val bxPro: PropertyValuesHolder
+ val byPro: PropertyValuesHolder
+ val bWidthPro: PropertyValuesHolder
+ val bHeightPro: PropertyValuesHolder
+ val alphaPro: PropertyValuesHolder
+ val bOA: 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
- )
+ val txPro: PropertyValuesHolder
+ val tyPro: PropertyValuesHolder
+ val tWidthPro: PropertyValuesHolder
+ val tHeightPro: PropertyValuesHolder
+ val tOA: ObjectAnimator
+
+ if (isSwapped) {
+ bxPro = PropertyValuesHolder.ofFloat("translationX", 0f, topX - bottomX - maxWidth * (1 - bScaleX) / 2)
+ byPro = PropertyValuesHolder.ofFloat("translationY",0f, topY - bottomY - maxHeight * (1 - bScaleY) / 2)
+ bWidthPro = PropertyValuesHolder.ofFloat("scaleX", 1f, bScaleX)
+ bHeightPro = PropertyValuesHolder.ofFloat("scaleY", 1f, bScaleY)
+ bOA = ObjectAnimator.ofPropertyValuesHolder(bottomView, bxPro, byPro, bWidthPro, bHeightPro)
+
+ txPro = PropertyValuesHolder.ofFloat("translationX", 0f, bottomX - topX - minWidth * (1 - tScaleX) / 2)
+ tyPro = PropertyValuesHolder.ofFloat("translationY", 0f, bottomY - topY - minHeight * (1 - tScaleY) / 2)
+ tWidthPro = PropertyValuesHolder.ofFloat("scaleX", 1f, tScaleX/1.5f)
+ tHeightPro = PropertyValuesHolder.ofFloat("scaleY", 1f, tScaleY/1.5f)
+ alphaPro = PropertyValuesHolder.ofFloat("alpha", 1f, 0.1f)
+ tOA = ObjectAnimator.ofPropertyValuesHolder(topView, tWidthPro, tHeightPro, txPro, tyPro, alphaPro)
} 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
- )
+ bxPro = PropertyValuesHolder.ofFloat("translationX", 0f, topX - bottomX - maxWidth * (1 - bScaleX) / 2)
+ byPro = PropertyValuesHolder.ofFloat("translationY",0f, topY - bottomY - maxHeight * (1 - bScaleY) / 2)
+ bWidthPro = PropertyValuesHolder.ofFloat("scaleX", 1f, bScaleX)
+ bHeightPro = PropertyValuesHolder.ofFloat("scaleY", 1f, bScaleY)
+ bOA = ObjectAnimator.ofPropertyValuesHolder(topView, bxPro, byPro, bWidthPro, bHeightPro)
+
+ txPro = PropertyValuesHolder.ofFloat("translationX", 0f, bottomX - topX - minWidth * (1 - tScaleX) / 2)
+ tyPro = PropertyValuesHolder.ofFloat("translationY", 0f, bottomY - topY - minHeight * (1 - tScaleY) / 2)
+ tWidthPro = PropertyValuesHolder.ofFloat("scaleX", 1f, tScaleX/1.5f)
+ tHeightPro = PropertyValuesHolder.ofFloat("scaleY", 1f, tScaleY/1.5f)
+ alphaPro = PropertyValuesHolder.ofFloat("alpha", 1f, 0.1f)
+ tOA = ObjectAnimator.ofPropertyValuesHolder(bottomView, tWidthPro, tHeightPro, txPro, tyPro, alphaPro)
+
+// // 如果只对内容做动画而不改变LayoutParams
+// bxPro = PropertyValuesHolder.ofFloat("translationX", bottomView.translationX, 0f)
+// byPro = PropertyValuesHolder.ofFloat("translationY", bottomView.translationY, 0f)
+// bWidthPro = PropertyValuesHolder.ofFloat("scaleX", bScaleX, 1f)
+// bHeightPro = PropertyValuesHolder.ofFloat("scaleY", bScaleY, 1f)
+// bOA = ObjectAnimator.ofPropertyValuesHolder(bottomView, bxPro, byPro, bWidthPro, bHeightPro)
+//
+// txPro = PropertyValuesHolder.ofFloat("translationX", topView.translationX, 0f)
+// tyPro = PropertyValuesHolder.ofFloat("translationY", topView.translationY, 0f)
+// tWidthPro = PropertyValuesHolder.ofFloat("scaleX", tScaleX, 1f)
+// tHeightPro = PropertyValuesHolder.ofFloat("scaleY", tScaleY, 1f)
+// tOA = ObjectAnimator.ofPropertyValuesHolder(topView, txPro, tyPro, tWidthPro, tHeightPro)
}
- // 将多个动画组合在一起
- val animatorSet = AnimatorSet()
- animatorSet.playTogether(
- bottomXAnimator,
- bottomYAnimator,
- bottomWidthAnimator,
- bottomHeightAnimator,
- topXAnimator,
- topYAnimator,
- topWidthAnimator,
- topHeightAnimator
+ animatorSet = AnimatorSet()
+ animatorSet?.playTogether(
+ bOA, tOA
)
- 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()
+ animatorSet?.duration = ANIM_DURATION
+ animatorSet?.addListener(animatorListener)
+ animatorSet?.start()
}
- fun getChangeFlag() = isChange
+ private val animatorListener = object : AnimatorListenerAdapter() {
+ override fun onAnimationStart(animation: Animator) {
+ super.onAnimationStart(animation)
+ isPlayingAnim = true
+ }
+
+ override fun onAnimationEnd(animation: Animator) {
+ super.onAnimationEnd(animation)
+// updateLayoutParams()
+ swapLayoutParamsWithoutAnim()
+ invalidate()
+ isPlayingAnim = false
+ }
+
+ override fun onAnimationCancel(animation: Animator) {
+ super.onAnimationCancel(animation)
+// updateLayoutParams()
+ swapLayoutParamsWithoutAnim()
+ invalidate()
+ isPlayingAnim = false
+ }
+ }
override fun isChildrenDrawingOrderEnabled() = super.isChildrenDrawingOrderEnabled()
override fun getChildDrawingOrder(childCount: Int, i: Int): Int {
- return if (isChange) {
+ return if (isSwapped) {
when (i) {
0 -> {
childCount - 1
@@ -223,60 +220,112 @@ class ExchangeChildLayout @JvmOverloads constructor(
}
}
- // 用于包装 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
- }
+ private fun updateLayoutParams() {
+// if (childCount > 2) return
+// children.forEachIndexed { index, view ->
+// if (index == 0) {
+// changeRule(view, true)
+// } else {
+// changeRule(view, false)
+// }
+// }
}
- 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
+ private fun changeRule(
+ view: View, isBottom: Boolean,
) {
+ val layoutParams = view.layoutParams as LayoutParams
if (isBottom) {
- if (isChange) {
+ if (isSwapped) {
layoutParams.startToStart = LayoutParams.UNSET
layoutParams.topToTop = LayoutParams.UNSET
layoutParams.endToEnd = LayoutParams.PARENT_ID
layoutParams.bottomToBottom = LayoutParams.PARENT_ID
+ layoutParams.width = minWidth
+ layoutParams.height = minHeight
} else {
layoutParams.startToStart = LayoutParams.PARENT_ID
layoutParams.topToTop = LayoutParams.PARENT_ID
layoutParams.endToEnd = LayoutParams.UNSET
layoutParams.bottomToBottom = LayoutParams.UNSET
+ layoutParams.width = maxWidth
+ layoutParams.height = maxHeight
}
} else {
- if (isChange) {
+ if (isSwapped) {
layoutParams.startToStart = LayoutParams.PARENT_ID
layoutParams.topToTop = LayoutParams.PARENT_ID
layoutParams.endToEnd = LayoutParams.UNSET
layoutParams.bottomToBottom = LayoutParams.UNSET
+ layoutParams.width = maxWidth
+ layoutParams.height = maxHeight
} else {
layoutParams.startToStart = LayoutParams.UNSET
layoutParams.topToTop = LayoutParams.UNSET
layoutParams.endToEnd = LayoutParams.PARENT_ID
layoutParams.bottomToBottom = LayoutParams.PARENT_ID
+ layoutParams.width = minWidth
+ layoutParams.height = minHeight
}
}
+ view.layoutParams = layoutParams
+ }
+
+ private fun swapLayoutParamsWithoutAnim() {
+ if (constraintUtil == null) {
+ constraintUtil = ConstraintUtil(exchangeLayout)
+ }
+ if (isSwapped) {
+ val begin = constraintUtil!!.begin()
+ // 清除约束关系
+ begin.clear(R.id.mapBizView, R.id.overMapView)
+ // 设置新的约束关系
+ begin.Left_toLeftOf(R.id.overMapView, ConstraintSet.PARENT_ID)
+ begin.Top_toTopOf(R.id.overMapView, ConstraintSet.PARENT_ID)
+ begin.Right_toRightOf(R.id.overMapView, ConstraintSet.PARENT_ID)
+ begin.Bottom_toBottomOf(R.id.overMapView, ConstraintSet.PARENT_ID)
+
+ begin.Left_toLeftOf(R.id.mapBizView, ConstraintSet.UNSET)
+ begin.Top_toTopOf(R.id.mapBizView, ConstraintSet.UNSET)
+ begin.Right_toRightOf(R.id.mapBizView, ConstraintSet.PARENT_ID)
+ begin.Bottom_toBottomOf(R.id.mapBizView, ConstraintSet.PARENT_ID)
+ begin.setWidth(R.id.mapBizView, AutoSizeUtils.dp2px(context, 270f))
+ begin.setHeight(R.id.mapBizView, AutoSizeUtils.dp2px(context, 270f))
+ begin.setMargin(
+ R.id.mapBizView,
+ 0,
+ 0,
+ AutoSizeUtils.dp2px(context, 60f),
+ AutoSizeUtils.dp2px(context, 60f)
+ )
+ // 应用新的属性集
+ begin.commit()
+ } else {
+// constraintUtil?.reSet()
+ val begin = constraintUtil!!.begin()
+ // 清除约束关系
+ begin.clear(R.id.mapBizView, R.id.overMapView)
+ // 设置新的约束关系
+ begin.Left_toLeftOf(R.id.mapBizView, ConstraintSet.PARENT_ID)
+ begin.Top_toTopOf(R.id.mapBizView, ConstraintSet.PARENT_ID)
+ begin.Right_toRightOf(R.id.mapBizView, ConstraintSet.PARENT_ID)
+ begin.Bottom_toBottomOf(R.id.mapBizView, ConstraintSet.PARENT_ID)
+
+ begin.Left_toLeftOf(R.id.overMapView, ConstraintSet.UNSET)
+ begin.Top_toTopOf(R.id.overMapView, ConstraintSet.UNSET)
+ begin.Right_toRightOf(R.id.overMapView, ConstraintSet.PARENT_ID)
+ begin.Bottom_toBottomOf(R.id.overMapView, ConstraintSet.PARENT_ID)
+ begin.setWidth(R.id.overMapView, AutoSizeUtils.dp2px(context, 270f))
+ begin.setHeight(R.id.overMapView, AutoSizeUtils.dp2px(context, 270f))
+ begin.setMargin(
+ R.id.overMapView,
+ 0,
+ 0,
+ AutoSizeUtils.dp2px(context, 60f),
+ AutoSizeUtils.dp2px(context, 60f)
+ )
+ // 应用新的属性集
+ begin.commit()
+ }
}
}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/map/MapContainerLayout.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/map/MapContainerLayout.kt
new file mode 100644
index 0000000000..9b47dfafff
--- /dev/null
+++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/map/MapContainerLayout.kt
@@ -0,0 +1,160 @@
+package com.mogo.eagle.core.function.hmi.map
+
+import android.content.Context
+import android.os.Bundle
+import android.transition.Transition
+import android.transition.Transition.TransitionListener
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.animation.DecelerateInterpolator
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.ConstraintSet
+import com.mogo.eagle.core.data.map.MogoLatLng
+import com.mogo.eagle.core.function.hmi.R
+import com.mogo.eagle.core.function.hmi.util.ConstraintUtil
+import com.mogo.eagle.core.function.view.TravelRealityView
+import com.mogo.map.listener.IMogoMapListener
+import com.mogo.map.listener.MogoMapListenerHandler
+import kotlinx.android.synthetic.main.view_map_container.view.exchangeLayout
+import kotlinx.android.synthetic.main.view_map_container.view.mapBizView
+import kotlinx.android.synthetic.main.view_map_container.view.overMapView
+import me.jessyan.autosize.utils.AutoSizeUtils
+
+class MapContainerLayout @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : ConstraintLayout(context, attrs, defStyleAttr), IMogoMapListener {
+
+ private var isSwapped = false
+ private var isPlayingAnim = false
+ private var constraintUtil: ConstraintUtil? = null
+
+ init {
+ LayoutInflater.from(context).inflate(R.layout.view_map_container, this, true)
+ initView()
+ }
+
+ companion object {
+ private const val TAG = "MapContainerLayout"
+ }
+
+ fun onCreate(savedInstanceState: Bundle?) {
+ mapBizView.onCreate(savedInstanceState)
+ overMapView.onCreateView(savedInstanceState)
+ }
+
+ fun onResume() {
+ mapBizView.onResume()
+ overMapView.onResume()
+ }
+
+ fun onPause() {
+ mapBizView.onPause()
+ overMapView.onPause()
+ }
+
+ fun onLowMemory() {
+ mapBizView.onLowMemory()
+ }
+
+ fun onSaveInstanceState(outState: Bundle) {
+ mapBizView.onSaveInstanceState(outState)
+ }
+
+ fun onDestroy() {
+ mapBizView.onDestroy()
+ overMapView.onDestroy()
+ }
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ MogoMapListenerHandler.mogoMapListenerHandler.registerHostMapListener("${TAG}${this.hashCode()}",this)
+ }
+
+ override fun onDetachedFromWindow() {
+ super.onDetachedFromWindow()
+ MogoMapListenerHandler.mogoMapListenerHandler.unregisterHostMapListener("${TAG}${this.hashCode()}")
+ }
+
+ private fun initView() {
+ overMapView.setOnGestureListener(object : TravelRealityView.OnGestureListener {
+ override fun onSingleTap(lng: Float, lat: Float) {
+ if (!exchangeLayout.getSwapFlag()) {
+ exchangeLayout.swapViews()
+ }
+ }
+ })
+ }
+
+ override fun onMapClick(latLng: MogoLatLng?) {
+ super.onMapClick(latLng)
+ if (exchangeLayout.getSwapFlag()) {
+ exchangeLayout.swapViews()
+ }
+ }
+
+ @Deprecated(message = "会多次requestLayout导致高精地图卡顿")
+ private fun swapViewsWithAnim() {
+ if (isPlayingAnim) return
+ if (constraintUtil == null) {
+ constraintUtil = ConstraintUtil(exchangeLayout, 300, DecelerateInterpolator())
+ constraintUtil?.addTransitionListener(transitionListener)
+ }
+ if (!isSwapped) {
+ // 获取属性集并设置动画
+ val begin = constraintUtil!!.beginWithAnim()
+ // 清除约束关系
+ begin.clear(R.id.mapBizView, R.id.overMapView)
+ // 设置新的约束关系
+ begin.Left_toLeftOf(R.id.overMapView, ConstraintSet.PARENT_ID)
+ begin.Top_toTopOf(R.id.overMapView, ConstraintSet.PARENT_ID)
+ begin.Right_toRightOf(R.id.overMapView, ConstraintSet.PARENT_ID)
+ begin.Bottom_toBottomOf(R.id.overMapView, ConstraintSet.PARENT_ID)
+
+ begin.Left_toLeftOf(R.id.mapBizView, ConstraintSet.UNSET)
+ begin.Top_toTopOf(R.id.mapBizView, ConstraintSet.UNSET)
+ begin.Right_toRightOf(R.id.mapBizView, ConstraintSet.PARENT_ID)
+ begin.Bottom_toBottomOf(R.id.mapBizView, ConstraintSet.PARENT_ID)
+ begin.setWidth(R.id.mapBizView, AutoSizeUtils.dp2px(context, 270f))
+ begin.setHeight(R.id.mapBizView, AutoSizeUtils.dp2px(context, 270f))
+ begin.setMargin(
+ R.id.mapBizView,
+ 0,
+ 0,
+ AutoSizeUtils.dp2px(context, 60f),
+ AutoSizeUtils.dp2px(context, 60f)
+ )
+ // 应用新的属性集
+ begin.commit()
+ exchangeLayout.setSwapped(true)
+ isSwapped = true
+ } else {
+ constraintUtil?.reSetWidthAnim()
+ exchangeLayout.setSwapped(false)
+ isSwapped = false
+ }
+ }
+
+ private val transitionListener = object : TransitionListener {
+ override fun onTransitionStart(transition: Transition?) {
+ isPlayingAnim = true
+ }
+
+ override fun onTransitionEnd(transition: Transition?) {
+ isPlayingAnim = false
+ }
+
+ override fun onTransitionCancel(transition: Transition?) {
+ isPlayingAnim = false
+ }
+
+ override fun onTransitionPause(transition: Transition?) {
+ isPlayingAnim = false
+ }
+
+ override fun onTransitionResume(transition: Transition?) {
+ isPlayingAnim = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/util/ConstraintUtil.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/util/ConstraintUtil.kt
new file mode 100644
index 0000000000..bd5639eaee
--- /dev/null
+++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/util/ConstraintUtil.kt
@@ -0,0 +1,350 @@
+package com.mogo.eagle.core.function.hmi.util
+
+import android.animation.TimeInterpolator
+import android.transition.AutoTransition
+import android.transition.Transition
+import android.transition.TransitionManager
+import android.view.animation.AccelerateDecelerateInterpolator
+import androidx.annotation.IdRes
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.ConstraintSet
+
+/**
+ * ConstraintSet工具类
+ */
+class ConstraintUtil private constructor() {
+ private var constraintLayout: ConstraintLayout? = null
+ private var begin: ConstraintBegin? = null
+ private val applyConstraintSet by lazy {
+ ConstraintSet()
+ }
+ private val resetConstraintSet by lazy {
+ ConstraintSet()
+ }
+
+ private val sDefaultTransition: Transition = AutoTransition()
+
+ constructor(constraintLayout: ConstraintLayout?) : this() {
+ this.constraintLayout = constraintLayout
+ resetConstraintSet.clone(constraintLayout)
+ }
+
+ constructor(constraintLayout: ConstraintLayout?, duration: Long, interpolator: TimeInterpolator) : this() {
+ this.constraintLayout = constraintLayout
+ resetConstraintSet.clone(constraintLayout)
+ sDefaultTransition.duration = duration
+ sDefaultTransition.interpolator = interpolator
+ }
+
+ /**
+ * 开始修改
+ *
+ * @return
+ */
+ fun begin(): ConstraintBegin {
+ synchronized(ConstraintBegin::class.java) {
+ if (begin == null) {
+ begin = ConstraintBegin()
+ }
+ }
+ applyConstraintSet.clone(constraintLayout)
+ return begin!!
+ }
+
+ /**
+ * 带动画的修改
+ *
+ * @return
+ */
+ fun beginWithAnim(): ConstraintBegin {
+ TransitionManager.beginDelayedTransition(constraintLayout, sDefaultTransition)
+ return begin()
+ }
+
+ /**
+ * 重置
+ */
+ fun reSet() {
+ resetConstraintSet.applyTo(constraintLayout)
+ }
+
+ /**
+ * 带动画的重置
+ */
+ fun reSetWidthAnim() {
+ TransitionManager.beginDelayedTransition(constraintLayout, sDefaultTransition)
+ resetConstraintSet.applyTo(constraintLayout)
+ }
+
+ /**
+ * 添加动画监听
+ *
+ * @param listener
+ */
+ fun addTransitionListener(listener: Transition.TransitionListener) {
+ sDefaultTransition.addListener(listener)
+ }
+
+ inner class ConstraintBegin {
+ /**
+ * 清除关系
+ * 注意:这里不仅仅会清除关系,还会清除对应控件的宽高为 w:0,h:0
+ *
+ * @param viewIds
+ * @return
+ */
+ fun clear(@IdRes vararg viewIds: Int): ConstraintBegin {
+ for (viewId in viewIds) {
+ applyConstraintSet.clear(viewId)
+ }
+ return this
+ }
+
+ /**
+ * 清除某个控件的,某个关系
+ *
+ * @param viewId
+ * @param anchor
+ * @return
+ */
+ fun clear(viewId: Int, anchor: Long): ConstraintBegin {
+ applyConstraintSet.clear(viewId, anchor.toInt())
+ return this
+ }
+
+ /**
+ * 为某个控件设置 margin
+ *
+ * @param viewId 某个控件ID
+ * @param left marginLeft
+ * @param top marginTop
+ * @param right marginRight
+ * @param bottom marginBottom
+ * @return
+ */
+ fun setMargin(
+ @IdRes viewId: Int,
+ left: Int,
+ top: Int,
+ right: Int,
+ bottom: Int
+ ): ConstraintBegin {
+ setMarginLeft(viewId, left)
+ setMarginTop(viewId, top)
+ setMarginRight(viewId, right)
+ setMarginBottom(viewId, bottom)
+ return this
+ }
+
+ /**
+ * 为某个控件设置 marginLeft
+ *
+ * @param viewId 某个控件ID
+ * @param left marginLeft
+ * @return
+ */
+ fun setMarginLeft(@IdRes viewId: Int, left: Int): ConstraintBegin {
+ applyConstraintSet.setMargin(viewId, ConstraintSet.LEFT, left)
+ return this
+ }
+
+ /**
+ * 为某个控件设置 marginRight
+ *
+ * @param viewId 某个控件ID
+ * @param right marginRight
+ * @return
+ */
+ fun setMarginRight(@IdRes viewId: Int, right: Int): ConstraintBegin {
+ applyConstraintSet.setMargin(viewId, ConstraintSet.RIGHT, right)
+ return this
+ }
+
+ /**
+ * 为某个控件设置 marginTop
+ *
+ * @param viewId 某个控件ID
+ * @param top marginTop
+ * @return
+ */
+ fun setMarginTop(@IdRes viewId: Int, top: Int): ConstraintBegin {
+ applyConstraintSet.setMargin(viewId, ConstraintSet.TOP, top)
+ return this
+ }
+
+ /**
+ * 为某个控件设置marginBottom
+ *
+ * @param viewId 某个控件ID
+ * @param bottom marginBottom
+ * @return
+ */
+ fun setMarginBottom(@IdRes viewId: Int, bottom: Int): ConstraintBegin {
+ applyConstraintSet.setMargin(viewId, ConstraintSet.BOTTOM, bottom)
+ return this
+ }
+
+ /**
+ * 为某个控件设置关联关系 left_to_left_of
+ *
+ * @param startId
+ * @param endId
+ * @return
+ */
+ fun Left_toLeftOf(@IdRes startId: Int, @IdRes endId: Int): ConstraintBegin {
+ applyConstraintSet.connect(startId, ConstraintSet.LEFT, endId, ConstraintSet.LEFT)
+ return this
+ }
+
+ /**
+ * 为某个控件设置关联关系 start_to_start_of
+ *
+ * @param startId
+ * @param endId
+ * @return
+ */
+ fun Start_toStartOf(@IdRes startId: Int, @IdRes endId: Int): ConstraintBegin {
+ applyConstraintSet.connect(startId, ConstraintSet.START, endId, ConstraintSet.START)
+ return this
+ }
+
+ /**
+ * 为某个控件设置关联关系 left_to_right_of
+ *
+ * @param startId
+ * @param endId
+ * @return
+ */
+ fun Left_toRightOf(@IdRes startId: Int, @IdRes endId: Int): ConstraintBegin {
+ applyConstraintSet.connect(startId, ConstraintSet.LEFT, endId, ConstraintSet.RIGHT)
+ return this
+ }
+
+ /**
+ * 为某个控件设置关联关系 top_to_top_of
+ *
+ * @param startId
+ * @param endId
+ * @return
+ */
+ fun Top_toTopOf(@IdRes startId: Int, @IdRes endId: Int): ConstraintBegin {
+ applyConstraintSet.connect(startId, ConstraintSet.TOP, endId, ConstraintSet.TOP)
+ return this
+ }
+
+ /**
+ * 为某个控件设置关联关系 top_to_bottom_of
+ *
+ * @param startId
+ * @param endId
+ * @return
+ */
+ fun Top_toBottomOf(@IdRes startId: Int, @IdRes endId: Int): ConstraintBegin {
+ applyConstraintSet.connect(startId, ConstraintSet.TOP, endId, ConstraintSet.BOTTOM)
+ return this
+ }
+
+ /**
+ * 为某个控件设置关联关系 right_to_left_of
+ *
+ * @param startId
+ * @param endId
+ * @return
+ */
+ fun Right_toLeftOf(@IdRes startId: Int, @IdRes endId: Int): ConstraintBegin {
+ applyConstraintSet.connect(startId, ConstraintSet.RIGHT, endId, ConstraintSet.LEFT)
+ return this
+ }
+
+ /**
+ * 为某个控件设置关联关系 right_to_right_of
+ *
+ * @param startId
+ * @param endId
+ * @return
+ */
+ fun Right_toRightOf(@IdRes startId: Int, @IdRes endId: Int): ConstraintBegin {
+ applyConstraintSet.connect(startId, ConstraintSet.RIGHT, endId, ConstraintSet.RIGHT)
+ return this
+ }
+
+ /**
+ * 为某个控件设置关联关系 bottom_to_bottom_of
+ *
+ * @param startId
+ * @param endId
+ * @return
+ */
+ fun Bottom_toBottomOf(@IdRes startId: Int, @IdRes endId: Int): ConstraintBegin {
+ applyConstraintSet.connect(startId, ConstraintSet.BOTTOM, endId, ConstraintSet.BOTTOM)
+ return this
+ }
+
+ /**
+ * 为某个控件设置关联关系 bottom_to_top_of
+ *
+ * @param startId
+ * @param endId
+ * @return
+ */
+ fun Bottom_toTopOf(@IdRes startId: Int, @IdRes endId: Int): ConstraintBegin {
+ applyConstraintSet.connect(startId, ConstraintSet.BOTTOM, endId, ConstraintSet.TOP)
+ return this
+ }
+
+ /**
+ * 为某个控件设置宽度
+ *
+ * @param viewId
+ * @param width
+ * @return
+ */
+ fun setWidth(@IdRes viewId: Int, width: Int): ConstraintBegin {
+ applyConstraintSet.constrainWidth(viewId, width)
+ return this
+ }
+
+ /**
+ * 某个控件设置高度
+ *
+ * @param viewId
+ * @param height
+ * @return
+ */
+ fun setHeight(@IdRes viewId: Int, height: Int): ConstraintBegin {
+ applyConstraintSet.constrainHeight(viewId, height)
+ return this
+ }
+
+ /**
+ * 为某个控件设置宽度百分比
+ *
+ * @param viewId
+ * @param percent
+ * @return
+ */
+ fun setWidthPercent(@IdRes viewId: Int, percent: Float): ConstraintBegin {
+ applyConstraintSet.constrainPercentWidth(viewId, percent)
+ return this
+ }
+
+ /**
+ * 某个控件设置高度百分比
+ *
+ * @param viewId
+ * @param percent
+ * @return
+ */
+ fun setHeightPercent(@IdRes viewId: Int, percent: Float): ConstraintBegin {
+ applyConstraintSet.constrainPercentHeight(viewId, percent)
+ return this
+ }
+
+ /**
+ * 提交应用生效
+ */
+ fun commit() {
+ applyConstraintSet.applyTo(constraintLayout)
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_map_container.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_map_container.xml
new file mode 100644
index 0000000000..5617a6b5d7
--- /dev/null
+++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_map_container.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/TravelRealityView.kt b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/TravelRealityView.kt
index 2c9f3a37a2..0974cec97e 100644
--- a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/TravelRealityView.kt
+++ b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/TravelRealityView.kt
@@ -19,6 +19,7 @@ import com.amap.api.maps.CameraUpdate
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.CoordinateConverter
import com.amap.api.maps.TextureMapView
+import com.amap.api.maps.model.AMapGestureListener
import com.amap.api.maps.model.BitmapDescriptor
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.CustomMapStyleOptions
@@ -205,6 +206,7 @@ class TravelRealityView @JvmOverloads constructor(
private var testTime = 0L
private var listener: OnDrawListener? = null
+ private var gestureListener: OnGestureListener? = null
init {
try {
@@ -272,6 +274,10 @@ class TravelRealityView @JvmOverloads constructor(
this.listener = listener
}
+ fun setOnGestureListener(listener: OnGestureListener) {
+ this.gestureListener = listener
+ }
+
/**
* 清除所有Marker和Polyline
*/
@@ -366,6 +372,32 @@ class TravelRealityView @JvmOverloads constructor(
mAMap?.uiSettings?.isZoomControlsEnabled = false
// mAMap?.animateCamera(CameraUpdateFactory.changeTilt(30f))
}
+ mAMap?.setAMapGestureListener(object : AMapGestureListener {
+ override fun onDoubleTap(p0: Float, p1: Float) {
+ }
+
+ override fun onSingleTap(p0: Float, p1: Float) {
+ gestureListener?.onSingleTap(p0, p1)
+ }
+
+ override fun onFling(p0: Float, p1: Float) {
+ }
+
+ override fun onScroll(p0: Float, p1: Float) {
+ }
+
+ override fun onLongPress(p0: Float, p1: Float) {
+ }
+
+ override fun onDown(p0: Float, p1: Float) {
+ }
+
+ override fun onUp(p0: Float, p1: Float) {
+ }
+
+ override fun onMapStable() {
+ }
+ })
}
override fun onVisibilityChanged(changedView: View, visibility: Int) {
@@ -1285,6 +1317,10 @@ class TravelRealityView @JvmOverloads constructor(
fun onDraw(eventList: List, isEvent: Boolean)
}
+ interface OnGestureListener {
+ fun onSingleTap(lng: Float, lat: Float)
+ }
+
private inner class NonFrequentHandler(looper: Looper) : Handler(looper) {
@Suppress("UNCHECKED_CAST")
override fun handleMessage(msg: Message) {
diff --git a/core/mogo-core-res/src/main/res/drawable-nodpi/taxi_orvermap_road_trajectory.png b/core/mogo-core-res/src/main/res/drawable-nodpi/taxi_orvermap_road_trajectory.png
new file mode 100644
index 0000000000..97d6b8470a
Binary files /dev/null and b/core/mogo-core-res/src/main/res/drawable-nodpi/taxi_orvermap_road_trajectory.png differ
diff --git a/core/mogo-core-res/src/main/res/drawable-nodpi/taxi_overmap_endpoint.png b/core/mogo-core-res/src/main/res/drawable-nodpi/taxi_overmap_endpoint.png
new file mode 100644
index 0000000000..61527f37c1
Binary files /dev/null and b/core/mogo-core-res/src/main/res/drawable-nodpi/taxi_overmap_endpoint.png differ
diff --git a/core/mogo-core-res/src/main/res/drawable-nodpi/taxi_overmap_road_range.png b/core/mogo-core-res/src/main/res/drawable-nodpi/taxi_overmap_road_range.png
new file mode 100644
index 0000000000..a6b03d50c6
Binary files /dev/null and b/core/mogo-core-res/src/main/res/drawable-nodpi/taxi_overmap_road_range.png differ