From 3d9640c8a6550d387de592242469caa1650ef6be Mon Sep 17 00:00:00 2001 From: chenfufeng Date: Mon, 23 Sep 2024 14:40:12 +0800 Subject: [PATCH] =?UTF-8?q?[6.7.0][Feat]=E9=AB=98=E7=B2=BE=E5=9C=B0?= =?UTF-8?q?=E5=9B=BE=E5=92=8C=E9=AB=98=E5=BE=B7=E5=9C=B0=E5=9B=BE=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E5=8A=A8=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../function/hmi/map/ExchangeChildLayout.kt | 379 ++++++++++-------- .../function/hmi/map/MapContainerLayout.kt | 160 ++++++++ .../core/function/hmi/util/ConstraintUtil.kt | 350 ++++++++++++++++ .../main/res/layout/view_map_container.xml | 48 +++ .../core/function/view/TravelRealityView.kt | 36 ++ .../taxi_orvermap_road_trajectory.png | Bin 0 -> 572 bytes .../drawable-nodpi/taxi_overmap_endpoint.png | Bin 0 -> 5218 bytes .../taxi_overmap_road_range.png | Bin 0 -> 573 bytes 8 files changed, 808 insertions(+), 165 deletions(-) create mode 100644 core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/map/MapContainerLayout.kt create mode 100644 core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/util/ConstraintUtil.kt create mode 100644 core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_map_container.xml create mode 100644 core/mogo-core-res/src/main/res/drawable-nodpi/taxi_orvermap_road_trajectory.png create mode 100644 core/mogo-core-res/src/main/res/drawable-nodpi/taxi_overmap_endpoint.png create mode 100644 core/mogo-core-res/src/main/res/drawable-nodpi/taxi_overmap_road_range.png 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 0000000000000000000000000000000000000000..97d6b8470abb9e0db916537216e08bd1b7ee40ea GIT binary patch literal 572 zcmeAS@N?(olHy`uVBq!ia0vp^GC-Wd!2~3w{;p#D` zHDb~SopfSK%a8X?4`frD_w!=3&LQ4l6?IGXljfd++rQYjL|V=%csU{L`tq-Pyrx`V zcu_aRxxczs^ZBB{-j!`~-=%`jxh|Fp=Cyrix@=Cjo9QyCsyo>}mg2oxKBixGT%S>- zCsn${N4lX#)O&BqosgED9G6c{lWUvsEcs^kHBp<2bfp~gyT>BZdYK=r>7P7r|M~uB z3qPB_F}YjCTzNwELrufudHa7WMDsd}XWx)5U;Q*>-)6lenZ3Vf=alT2axGs-HDZ~# z_l8>rCNKU)7cW_;FZU@_=V|>DE4RB3H9hB)bl6Ti?c;iTf6vCNUuVbupQ>?sN|%Z2 zlyyx`YEzAG_?>%@`)$Dz&2YnSN&6?vd1_i#dHBM&1M+(oPOgu>lrgjD|JCzu5uC;X zT+9Dn30As3LXP+E?A2Vn=yK1>KKWwlU^mz0lEJd}&&-zf ubom)Cv#L9j>mw;TH_fN?&y3&y4gRvQx5e)e$lWy^6my=gelF{r5}E*XS>#Co literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..61527f37c106c8ec1b5135679a3398d427b9090b GIT binary patch literal 5218 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..a6b03d50c6b2cefd1a492f6f653ac15944f0bec9 GIT binary patch literal 573 zcmeAS@N?(olHy`uVBq!ia0vp^At21b1|(&&1r7o!#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyy~KS-^~7gA{JhIO_mZw%pUjF{Fa= z?OnsH!ww9r7uURdd`HD{4S!lqgTnH=vIUB12hZ-fr10O>=1TURdCyT^gto4}hF0_~{_@ZUwW1|bQU6&;hf`+OTf zHCd~iRTZ8$2Dy|i5SsAWK~u>(fb&G<0+ETbD_EY`1azI?3t=jf({N2;*J8BfpQ5yh zd1}KPb}zx3jb0Atn3s0EaTqSzFK&16*!1mc{*{tfU2S>I*tkv(3*#T7&mu|t T!|XEyKvC!E>gTe~DWM4f`yI#o literal 0 HcmV?d00001