diff --git a/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/entrance/EntranceFragment.java b/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/entrance/EntranceFragment.java index 2afba379f1..a70c9bfc85 100644 --- a/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/entrance/EntranceFragment.java +++ b/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/entrance/EntranceFragment.java @@ -1,8 +1,10 @@ package com.mogo.module.extensions.entrance; import android.content.Intent; +import android.content.SharedPreferences; import android.graphics.Rect; import android.os.Bundle; +import android.os.Handler; import android.text.TextUtils; import android.util.TypedValue; import android.view.LayoutInflater; @@ -16,6 +18,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; +import androidx.constraintlayout.widget.Group; import com.alibaba.android.arouter.launcher.ARouter; import com.bumptech.glide.request.RequestOptions; @@ -26,7 +29,6 @@ import com.mogo.commons.voice.AIAssist; import com.mogo.map.MogoLatLng; import com.mogo.map.listener.IMogoMapListener; import com.mogo.map.location.IMogoLocationClient; -import com.mogo.map.location.MogoLocation; import com.mogo.map.marker.IMogoMarkerManager; import com.mogo.map.navi.IMogoAimlessModeListener; import com.mogo.map.navi.IMogoNavi; @@ -48,9 +50,11 @@ import com.mogo.module.extensions.navi.NaviInfoView; import com.mogo.module.extensions.userinfo.UserInfo; import com.mogo.module.extensions.utils.EntranceViewHolder; import com.mogo.module.extensions.utils.TopViewAnimHelper; +import com.mogo.module.extensions.utils.TopViewNoLinkageAnimHelper; import com.mogo.module.share.manager.ServiceApisManager; import com.mogo.service.IMogoServiceApis; import com.mogo.service.analytics.IMogoAnalytics; +import com.mogo.service.connection.IMogoOnMessageListener; import com.mogo.service.entrance.ButtonIndex; import com.mogo.service.fragmentmanager.IFragmentProvider; import com.mogo.service.fragmentmanager.IMogoFragmentManager; @@ -174,10 +178,14 @@ public class EntranceFragment extends MvpFragment seekHelpGroup.setVisibility(View.GONE)); + } } } @@ -880,6 +901,36 @@ public class EntranceFragment extends MvpFragment seekHelpNoticeListener = + new IMogoOnMessageListener() { + @Override + public Class target() { + return String.class; + } + + @Override + public void onMsgReceived(String obj) { + if(mStatusManager.isSeekHelping()) { + int seekNum = SharedPrefsMgr.getInstance(getContext()).getInt("seek_help_num", 0); + final int finalSeekNum = seekNum++; + SharedPrefsMgr.getInstance(getContext()).putInt("seek_help_num", seekNum); + handler.post(() -> { + seekHelpGroup.setVisibility(View.VISIBLE); + seekHelpNum.setText("" + finalSeekNum); + }); + } + } + }; + + private Handler handler = new Handler(); + + private void listenSeekNumber(){ + mApis.getSocketManagerApi(getContext()).registerOnMessageListener(SEEK_HELP_NOTICE_NUM_MSG_TYPE, seekHelpNoticeListener); + mStatusManager.registerStatusChangedListener(TAG,StatusDescriptor.SEEK_HELPING,this); + } + @Override public void onDestroy() { super.onDestroy(); @@ -892,11 +943,13 @@ public class EntranceFragment extends MvpFragment { - topContainer.setChildAddedListener(null); - if (naviBg.getVisibility() == View.VISIBLE) { - remainDistanceGroup.setVisibility(View.GONE); - remainTimeGroup.setVisibility(View.GONE); - arriveTimeGroup.setVisibility(View.GONE); - } + try { + topContainer.setChildAddedListener(null); + if (naviBg.getVisibility() == View.VISIBLE) { + remainDistanceGroup.setVisibility(View.GONE); + remainTimeGroup.setVisibility(View.GONE); + arriveTimeGroup.setVisibility(View.GONE); + } - constraintSet.clone(topMotionLayout); + constraintSet.clone(topMotionLayout); - constraintSet.clear(R.id.module_entrance_id_top_container, - ConstraintSet.BOTTOM); - constraintSet.connect(R.id.module_entrance_id_top_container, ConstraintSet.TOP, - R.id.module_entrance_id_top_motion_layout, ConstraintSet.TOP); + constraintSet.clear(R.id.module_entrance_id_top_container, + ConstraintSet.BOTTOM); + constraintSet.connect(R.id.module_entrance_id_top_container, + ConstraintSet.TOP, + R.id.module_entrance_id_top_motion_layout, ConstraintSet.TOP); // if (CarSeries.getSeries() == CarSeries.CAR_SERIES_F80X) { - TransitionManager.beginDelayedTransition(topMotionLayout, transition); + TransitionManager.beginDelayedTransition(topMotionLayout, transition); // } - checkCameraModePosition(false); - if (naviBg.getVisibility() == View.VISIBLE) { - // 约束设置需要在applyTo()方法之前执行,visiable设置需要在applyTo() - // 方法之后执行才能生效,所以分开了两个判断,至于为什么这么做才能生效,不得而知 - constraintSet.connect(tvNextDistance.getId(), ConstraintSet.BOTTOM, - ivTurnIcon.getId(), ConstraintSet.BOTTOM); - constraintSet.connect(ivTurnIcon.getId(), ConstraintSet.LEFT, - naviBg.getId(), ConstraintSet.LEFT, - (int) getDimen(R.dimen.module_ext_navi_info_panel_turn_icon_small_marginLeft)); + checkCameraModePosition(false); + if (naviBg.getVisibility() == View.VISIBLE) { + // 约束设置需要在applyTo()方法之前执行,visiable设置需要在applyTo() + // 方法之后执行才能生效,所以分开了两个判断,至于为什么这么做才能生效,不得而知 + constraintSet.connect(tvNextDistance.getId(), ConstraintSet.BOTTOM, + ivTurnIcon.getId(), ConstraintSet.BOTTOM); + constraintSet.connect(ivTurnIcon.getId(), ConstraintSet.LEFT, + naviBg.getId(), ConstraintSet.LEFT, + (int) getDimen(R.dimen.module_ext_navi_info_panel_turn_icon_small_marginLeft)); // constraintSet.clear(tvNextRoad.getId(), ConstraintSet.BOTTOM); - constraintSet.connect(tvNextRoad.getId(), ConstraintSet.BOTTOM, - tvNextDistance.getId(), ConstraintSet.BOTTOM, - (int) getDimen(R.dimen.module_map_id_navi_next_info_road_marginBottom_small)); - constraintSet.connect(tvNextRoad.getId(), ConstraintSet.LEFT, - R.id.module_map_id_navi_next_info_turn_info, ConstraintSet.RIGHT, - (int) topMotionLayout.getContext().getResources().getDimension(R.dimen.dp_46)); + constraintSet.connect(tvNextRoad.getId(), ConstraintSet.BOTTOM, + tvNextDistance.getId(), ConstraintSet.BOTTOM, + (int) getDimen(R.dimen.module_map_id_navi_next_info_road_marginBottom_small)); + constraintSet.connect(tvNextRoad.getId(), ConstraintSet.LEFT, + R.id.module_map_id_navi_next_info_turn_info, + ConstraintSet.RIGHT, + (int) topMotionLayout.getContext().getResources().getDimension(R.dimen.dp_46)); - constraintSet.clear(ivTurnIcon.getId(), ConstraintSet.TOP); - constraintSet.connect(ivTurnIcon.getId(), ConstraintSet.BOTTOM, - naviBg.getId(), ConstraintSet.BOTTOM, - (int) getDimen(R.dimen.module_ext_navi_info_turn_icon_margin_bottom)); + constraintSet.clear(ivTurnIcon.getId(), ConstraintSet.TOP); + constraintSet.connect(ivTurnIcon.getId(), ConstraintSet.BOTTOM, + naviBg.getId(), ConstraintSet.BOTTOM, + (int) getDimen(R.dimen.module_ext_navi_info_turn_icon_margin_bottom)); - constraintSet.connect(naviBg.getId(), ConstraintSet.TOP, - R.id.module_entrance_id_top_motion_layout, ConstraintSet.TOP, - computeNaviMarginTop(params.height)); + constraintSet.connect(naviBg.getId(), ConstraintSet.TOP, + R.id.module_entrance_id_top_motion_layout, ConstraintSet.TOP, + computeNaviMarginTop(params.height)); - // 动态改变相关字体大小 - tvNextDistance.setTextSize(TypedValue.COMPLEX_UNIT_PX,getDimen(R.dimen.module_ext_navi_info_panel_next_info_distance_textSize_small)); - tvNextDistanceUnit.setTextSize(TypedValue.COMPLEX_UNIT_PX,getDimen(R.dimen.module_ext_navi_info_panel_next_info_distance_unit_textSize_small)); + // 动态改变相关字体大小 + tvNextDistance.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getDimen(R.dimen.module_ext_navi_info_panel_next_info_distance_textSize_small)); + tvNextDistanceUnit.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getDimen(R.dimen.module_ext_navi_info_panel_next_info_distance_unit_textSize_small)); + } + constraintSet.applyTo(topMotionLayout); + ivTurnIcon.getLayoutParams().height = + (int) getDimen(R.dimen.module_ext_navi_info_panel_turn_icon_small_height); + ivTurnIcon.getLayoutParams().width = + (int) getDimen(R.dimen.module_ext_navi_info_panel_turn_icon_small_width); + naviBg.getLayoutParams().height = + (int) topMotionLayout.getContext().getResources().getDimension(R.dimen.module_ext_navi_info_panel_small_height); + int scene = 0; + if (naviBg.getVisibility() == View.VISIBLE) { + scene = Scene.NAVI_WITH_ROAD_EVENT; + } else { + scene = Scene.AIMLESS_WITH_ROAD_EVENT; + } + Logger.d(TAG, "show top setMapCenterPointByScene: " + scene); + MapCenterPointStrategy.setMapCenterPointByScene(mogoMapUIController, scene); + } catch (Exception e) { + Logger.e(TAG, e, "添加view异常"); + e.printStackTrace(); } - constraintSet.applyTo(topMotionLayout); - ivTurnIcon.getLayoutParams().height = - (int) getDimen(R.dimen.module_ext_navi_info_panel_turn_icon_small_height); - ivTurnIcon.getLayoutParams().width = - (int) getDimen(R.dimen.module_ext_navi_info_panel_turn_icon_small_width); - naviBg.getLayoutParams().height = - (int) topMotionLayout.getContext().getResources().getDimension(R.dimen.module_ext_navi_info_panel_small_height); - int scene = 0; - if (naviBg.getVisibility() == View.VISIBLE) { - scene = Scene.NAVI_WITH_ROAD_EVENT; - } else { - scene = Scene.AIMLESS_WITH_ROAD_EVENT; - } - Logger.d(TAG, "show top setMapCenterPointByScene: " + scene); - MapCenterPointStrategy.setMapCenterPointByScene(mogoMapUIController, scene); }); } } diff --git a/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/utils/TopViewManager.java b/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/utils/TopViewManager.java index 29a161821c..ce1e39e34f 100644 --- a/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/utils/TopViewManager.java +++ b/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/utils/TopViewManager.java @@ -51,6 +51,30 @@ public class TopViewManager implements IMogoTopViewManager { TopViewAnimHelper.getInstance().startTopInAnim(view, params, statusListener); } + @Override + public void addViewNoLinkage(View view) { + addViewNoLinkage(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + (int) context.getResources().getDimension(R.dimen.dp_350)), null); + } + + @Override + public void addViewNoLinkage(View view, IMogoTopViewStatusListener statusListener) { + addViewNoLinkage(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + (int) context.getResources().getDimension(R.dimen.dp_350)), statusListener); + } + + @Override + public void addViewNoLinkage(View view, ViewGroup.LayoutParams params) { + addViewNoLinkage(view, params, null); + } + + @Override + public void addViewNoLinkage(View view, ViewGroup.LayoutParams params, + IMogoTopViewStatusListener statusListener) { + parentParams = params; + TopViewNoLinkageAnimHelper.getInstance().startTopInAnim(view, params, statusListener); + } + @Override public void addSubView(View view) { addSubView(view, null); @@ -66,6 +90,11 @@ public class TopViewManager implements IMogoTopViewManager { TopViewAnimHelper.getInstance().startTopOutAnim(view); } + @Override + public void removeViewNoLinkage(View view) { + TopViewNoLinkageAnimHelper.getInstance().startTopOutAnim(view); + } + @Override public void removeSubView(View view) { TopViewAnimHelper.getInstance().removeSubView(view); @@ -75,4 +104,9 @@ public class TopViewManager implements IMogoTopViewManager { public boolean isViewAdded(View view) { return TopViewAnimHelper.getInstance().isViewAdded(view); } + + @Override + public boolean isViewNoLinkageAdded(View view) { + return TopViewNoLinkageAnimHelper.getInstance().isViewAdded(view); + } } diff --git a/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/utils/TopViewNoLinkageAnimHelper.java b/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/utils/TopViewNoLinkageAnimHelper.java new file mode 100644 index 0000000000..ce48c7d1e7 --- /dev/null +++ b/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/utils/TopViewNoLinkageAnimHelper.java @@ -0,0 +1,535 @@ +package com.mogo.module.extensions.utils; + +import android.animation.Animator; +import android.os.Handler; +import android.transition.AutoTransition; +import android.transition.Transition; +import android.transition.TransitionManager; +import android.util.ArrayMap; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.ConstraintSet; +import androidx.constraintlayout.widget.Group; + +import com.mogo.map.uicontroller.IMogoMapUIController; +import com.mogo.module.common.MogoApisHandler; +import com.mogo.module.common.map.MapCenterPointStrategy; +import com.mogo.module.common.map.Scene; +import com.mogo.module.extensions.ExtensionsModuleConst; +import com.mogo.module.extensions.R; +import com.mogo.module.extensions.navi.TopView; +import com.mogo.service.windowview.IMogoTopViewStatusListener; +import com.mogo.utils.logger.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +/** + * 顶部动画帮助类,与其他控件无关练 + * + * @author tongchenfei + */ +public class TopViewNoLinkageAnimHelper { + private static final String TAG = "TopViewNoLinkageAnimHelper"; + + private ConstraintLayout topMotionLayout; + private Group remainTimeGroup, remainDistanceGroup, arriveTimeGroup; + private View naviBg; + + private ImageView ivTurnIcon; + private TextView tvNextDistance; + private TextView tvNextRoad; + private TextView tvNextDistanceUnit; + private TextView tvTurnInfo; + private TopView topContainerNoLinkage; + + private ConstraintSet constraintSet; + private Transition transition; + private TextView cameraMode; + + private float topHeight = 0f; + + private Handler handler = new Handler(); + + private TopViewNoLinkageAnimHelper() { + } + + private volatile static TopViewNoLinkageAnimHelper instance = null; + + public static TopViewNoLinkageAnimHelper getInstance() { + if (instance == null) { + synchronized (TopViewNoLinkageAnimHelper.class) { + if (instance == null) { + instance = new TopViewNoLinkageAnimHelper(); + } + } + } + return instance; + } + + private IMogoMapUIController mogoMapUIController; + + public void setIMogoMapUIController(IMogoMapUIController mogoMapUIController) { + this.mogoMapUIController = mogoMapUIController; + } + + public void init(ConstraintLayout rootView) { + init(rootView, null); + } + + public void init(ConstraintLayout rootView, OnTopViewAnimSimpleListener listener) { + + constraintSet = new ConstraintSet(); + transition = new AutoTransition(); + + topMotionLayout = rootView; + naviBg = rootView.findViewById(R.id.module_map_id_navi_bg); + remainTimeGroup = rootView.findViewById(R.id.remainTimeGroup); + remainDistanceGroup = rootView.findViewById(R.id.remainDistanceGroup); + arriveTimeGroup = rootView.findViewById(R.id.arriveTimeGroup); + topContainerNoLinkage = rootView.findViewById(R.id.module_entrance_id_top_container_no_linkage); + tvNextDistanceUnit = rootView.findViewById(R.id.module_map_id_navi_next_info_distance_unit); + tvTurnInfo = rootView.findViewById(R.id.module_map_id_navi_next_info_turn_info); + + topContainerNoLinkage.setSlideListener(this::startLatestTopOutAnim); + + ivTurnIcon = rootView.findViewById(R.id.module_map_id_navi_next_info_road_turn_icon); + tvNextDistance = rootView.findViewById(R.id.module_map_id_navi_next_info_distance); + tvNextRoad = rootView.findViewById(R.id.module_map_id_navi_next_info_road); + transition.setDuration(200); + + transition.addListener(new Transition.TransitionListener() { + @Override + public void onTransitionStart(Transition transition) { + if (listener != null) { + listener.onAnimStart(); + } + } + + @Override + public void onTransitionEnd(Transition transition) { +// if (isTopViewOut) { +// topContainer.removeAllViews(); +// } + if (listener != null) { + listener.onAnimEnd(); + } + Logger.d(TAG, "onTransitionEnd: " + currentAnimatingView); + IMogoTopViewStatusListener listener; + if (isTopViewOut) { + int lastCount = topContainerNoLinkage.getChildCount(); + for (int i = 0; i < lastCount; i++) { + View child = topContainerNoLinkage.getChildAt(i); + viewCaches.remove(child); + listener = statusListenerMap.remove(child); + if (listener != null) { + listener.onViewRemoved(child); + } + } + topContainerNoLinkage.removeAllViews(); + } else { + listener = statusListenerMap.get(currentAnimatingView); + if (listener != null) { + listener.onViewAdded(currentAnimatingView); + } + } + } + + @Override + public void onTransitionCancel(Transition transition) { + + } + + @Override + public void onTransitionPause(Transition transition) { + + } + + @Override + public void onTransitionResume(Transition transition) { + + } + }); + + cameraMode = rootView.findViewById(R.id.module_ext_id_north); + // 初始化默认隐藏导航 + hideNaviView(); + } + + private volatile boolean isTopViewOut = true; + private List viewCaches = new ArrayList<>(); + private Map statusListenerMap = new ArrayMap<>(); + + private View currentAnimatingView = null; + + public void addSubView(View subView, LayoutParams params, + IMogoTopViewStatusListener statusListener) { + if (isTopViewOut || topContainerNoLinkage.getChildCount() == 0) { + throw new IllegalStateException("no base view in top view"); + } + if (subView == null) { + throw new IllegalArgumentException("method addTopView params view is null"); + } + if (params == null) { + throw new IllegalArgumentException("method addTopView params LayoutParams is null"); + } + + // 是在已经添加过view之后,才能添加sub view,所以直接走增加小view的逻辑就行 + if (!viewCaches.contains(subView)) { + viewCaches.add(subView); + statusListenerMap.put(subView, statusListener); + subView.setTranslationY(0); + subView.setTranslationY(-(params.height)); + topContainerNoLinkage.addView(subView, params); + Logger.d(TAG, "添加subView: " + subView.getTranslationY() + " height:" + + " " + subView.getHeight() + " paramsHeight: " + params.height); + if (statusListenerMap.get(subView) != null) { + statusListenerMap.get(subView).beforeViewAddAnim(subView); + } + subView.animate().translationY(0).setDuration(500).setListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + IMogoTopViewStatusListener listener = statusListenerMap.get(subView); + if (listener != null) { + listener.onViewAdded(subView); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }).start(); + } + + } + + public void removeSubView(View subView) { + if (topContainerNoLinkage.getChildCount() < 2) { + throw new IllegalStateException("view count not enough"); + } + Logger.d(TAG, + "小view退出: " + subView.getTranslationY() + " height: " + subView.getHeight()); + if (statusListenerMap.get(subView) != null) { + statusListenerMap.get(subView).beforeViewRemoveAnim(subView); + } + subView.animate().translationY(-(subView.getHeight())).setDuration(500).setListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + Logger.d(TAG, "onAnimationEnd: " + subView); + viewCaches.remove(subView); + topContainerNoLinkage.removeView(subView); + IMogoTopViewStatusListener listener = statusListenerMap.remove(subView); + if (listener != null) { + listener.onViewRemoved(subView); + } else { + Logger.d(TAG, "listener is null"); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + viewCaches.remove(subView); + topContainerNoLinkage.removeView(subView); + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }).start(); + } + + public void startTopInAnim(View view, LayoutParams params, + IMogoTopViewStatusListener statusListener) { + + if (topMotionLayout == null) { + return; + } + + Logger.d(TAG, "startTopInAnim=====" + isTopViewOut); + if (view == null) { + throw new IllegalArgumentException("method addTopView params view is null"); + } + if (params == null) { + throw new IllegalArgumentException("method addTopView params LayoutParams is null"); + } + if (!viewCaches.contains(view)) { + // 判断此view是否已经增加到了顶部view,如果增加过就不增加了 + view.setTranslationY(0); + statusListenerMap.put(view, statusListener); + Logger.d(TAG, "开始执行"); + isTopViewOut = false; + if (topContainerNoLinkage.getChildCount() > 0) { + // 顶部view已经有了内容,新增内容无需整体布局变化,只是新增布局加个动画 + viewCaches.add(view); + + // 生硬的删掉之前的view + int lastCount = topContainerNoLinkage.getChildCount(); + Logger.d(TAG, "进入动画,lastCount: " + lastCount); + for (int i = 0; i < lastCount; i++) { + View lastView = topContainerNoLinkage.getChildAt(i); + if (statusListenerMap.get(lastView) != null) { + statusListenerMap.get(lastView).beforeViewRemoveAnim(lastView); + } + viewCaches.remove(lastView); + if (statusListenerMap.get(lastView) != null) { + statusListenerMap.remove(lastView).onViewRemoved(lastView); + } + } + Logger.d(TAG, "生硬的删掉了之前的view: " + viewCaches.size()); + topContainerNoLinkage.removeAllViews(); + // 同时设置一下隐藏状态 + MogoApisHandler.getInstance().getApis().getStatusManagerApi().setTopViewShow(ExtensionsModuleConst.TYPE_ENTRANCE, false); + + // 如果高度变化,生硬的变化一下高度 + Logger.d(TAG, "container.height: " + topContainerNoLinkage.getHeight()); + if (topContainerNoLinkage.getHeight() != params.height) { + constraintSet.clone(topMotionLayout); + LayoutParams p = topContainerNoLinkage.getLayoutParams(); + p.height = params.height; + topContainerNoLinkage.setLayoutParams(p); + constraintSet.connect(naviBg.getId(), ConstraintSet.TOP, + R.id.module_entrance_id_top_motion_layout, ConstraintSet.TOP, + computeNaviMarginTop(params.height)); + constraintSet.applyTo(topMotionLayout); + Logger.d(TAG, "改变container的高度==="); + } + + view.setTranslationY(-(params.height)); + topContainerNoLinkage.addView(view, params); + Logger.d(TAG, "顶部view已经有布局了,增加新增view滑入动画: " + view.getTranslationY() + " height:" + + " " + view.getHeight() + " paramsHeight: " + params.height); + if (statusListenerMap.get(view) != null) { + statusListenerMap.get(view).beforeViewAddAnim(view); + } + view.animate().translationY(0).setDuration(500).setListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + IMogoTopViewStatusListener listener = statusListenerMap.get(view); + if (listener != null) { + listener.onViewAdded(view); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }).start(); + } else { + // 顶部view还没有内容,需要整体下移 + currentAnimatingView = view; + viewCaches.add(view); + topContainerNoLinkage.addView(view, params); + Logger.d(TAG, "整体进入==== view.visibility: " + view.getVisibility() + " view" + + ".position: (" + view.getX() + ", " + view.getY() + ") params.width: " + params.width + " params.height: " + params.height); + if (statusListenerMap.get(view) != null) { + statusListenerMap.get(view).beforeViewAddAnim(view); + } + topContainerNoLinkage.setChildAddedListener(child -> { + topContainerNoLinkage.setChildAddedListener(null); + constraintSet.clone(topMotionLayout); + + constraintSet.clear(R.id.module_entrance_id_top_container_no_linkage, + ConstraintSet.BOTTOM); + constraintSet.connect(R.id.module_entrance_id_top_container_no_linkage, ConstraintSet.TOP, + R.id.module_entrance_id_top_motion_layout, ConstraintSet.TOP); + TransitionManager.beginDelayedTransition(topMotionLayout, transition); + checkCameraModePosition(false); + + constraintSet.applyTo(topMotionLayout); + + int scene = Scene.AIMLESS_WITH_ROAD_EVENT; + Logger.d(TAG, "show top setMapCenterPointByScene: " + scene); + MapCenterPointStrategy.setMapCenterPointByScene(mogoMapUIController, scene); + }); + } + } + + MogoApisHandler.getInstance().getApis().getStatusManagerApi().setTopViewShow(ExtensionsModuleConst.TYPE_ENTRANCE, true); + } + + /** + * 退出最新的(也就是最上面的)view + */ + private void startLatestTopOutAnim() { + if (topContainerNoLinkage.getChildCount() > 1) { + removeSubView(topContainerNoLinkage.getChildAt(topContainerNoLinkage.getChildCount() - 1)); + } else if (topContainerNoLinkage.getChildCount() > 0) { + startTopOutAnim(topContainerNoLinkage.getChildAt(topContainerNoLinkage.getChildCount() - 1)); + } + } + + public void startTopOutAnim(View view) { + if (topMotionLayout == null) { + return; + } + Logger.d(TAG, "startTopOutAnim====="); + if (!isTopViewOut && viewCaches.contains(view)) { + // 顶部view仅剩一个view,需要整体上移 + if (statusListenerMap.get(view) != null) { + statusListenerMap.get(view).beforeViewRemoveAnim(view); + } + isTopViewOut = true; + constraintSet.clone(topMotionLayout); + + constraintSet.clear(R.id.module_entrance_id_top_container_no_linkage, ConstraintSet.TOP); + constraintSet.connect(R.id.module_entrance_id_top_container_no_linkage, ConstraintSet.BOTTOM, + R.id.module_entrance_id_top_motion_layout, ConstraintSet.TOP); + TransitionManager.beginDelayedTransition(topMotionLayout, transition); + checkCameraModePosition(false); + + constraintSet.applyTo(topMotionLayout); + + int scene = Scene.AIMLESS; + Logger.d(TAG, "hide top setMapCenterPointByScene: " + scene); + MapCenterPointStrategy.setMapCenterPointByScene(mogoMapUIController, scene); + MogoApisHandler.getInstance().getApis().getStatusManagerApi().setTopViewShow(ExtensionsModuleConst.TYPE_ENTRANCE, false); + } + } + + public void hideNaviView() { + if (topMotionLayout == null) { + return; + } + + Logger.d(TAG, "hideNaviView====="); + setNaviVisibility(View.GONE); + remainDistanceGroup.setVisibility(View.GONE); + remainTimeGroup.setVisibility(View.GONE); + arriveTimeGroup.setVisibility(View.GONE); + int scene = 0; + if (isTopViewOut) { + scene = Scene.AIMLESS; + } else { + scene = Scene.AIMLESS_WITH_ROAD_EVENT; + } + Logger.d(TAG, "hide navi setMapCenterPointByScene: " + scene); + MapCenterPointStrategy.setMapCenterPointByScene(mogoMapUIController, scene); + checkCameraModePosition(true); + } + + private void checkCameraModePosition(boolean isNeedClone) { + if (isNeedClone) { + constraintSet.clone(topMotionLayout); + } + if (naviBg.getVisibility() == View.VISIBLE) { + constraintSet.connect(cameraMode.getId(), ConstraintSet.TOP, naviBg.getId(), + ConstraintSet.BOTTOM, (int) getDimen(R.dimen.dp_30)); + } else { + if (isTopViewOut) { + constraintSet.connect(cameraMode.getId(), ConstraintSet.TOP, naviBg.getId(), + ConstraintSet.BOTTOM, + (int) getDimen(R.dimen.module_ext_north_goneMarginTop)); + } else { + constraintSet.connect(cameraMode.getId(), ConstraintSet.TOP, + R.id.module_entrance_id_top_container_no_linkage, + ConstraintSet.BOTTOM, + (int) getDimen(R.dimen.dp_30)); + } + } + if (isNeedClone) { + constraintSet.applyTo(topMotionLayout); + } + } + + private float getDimen(int resId) { + return (int) topMotionLayout.getContext().getResources().getDimensionPixelSize(resId); + } + + private int computeNaviMarginTop(int height) { + int result = (int) (height - (getDimen(R.dimen.module_ext_top_over_navi_height)) - getDimen(R.dimen.module_common_shadow_width_pos)); + Logger.d(TAG, "computeNaviMarginTop: " + height + " result: " + result); + return result; + } + + interface OnTopViewAnimSimpleListener { + void onAnimStart(); + + void onAnimEnd(); + } + + public boolean isViewAdded(View view) { + return viewCaches.contains(view); + } + + private void setNaviVisibility(int visibility) { + ivTurnIcon.setVisibility(visibility); + tvNextRoad.setVisibility(visibility); + tvNextDistance.setVisibility(visibility); + remainTimeGroup.setVisibility(visibility); + remainDistanceGroup.setVisibility(visibility); + arriveTimeGroup.setVisibility(visibility); + naviBg.setVisibility(visibility); + tvNextDistanceUnit.setVisibility(visibility); + tvTurnInfo.setVisibility(visibility); + } + + public void removeAllView() { + Logger.d(TAG, "remove all view"); + isTopViewOut = true; + int lastCount = topContainerNoLinkage.getChildCount(); + for (int i = 0; i < lastCount; i++) { + View child = topContainerNoLinkage.getChildAt(i); + viewCaches.remove(child); + IMogoTopViewStatusListener listener = statusListenerMap.remove(child); + if (listener != null) { + listener.beforeViewRemoveAnim(child); + listener.onViewRemoved(child); + } + } + topContainerNoLinkage.removeAllViews(); + hideNaviView(); + MapCenterPointStrategy.setMapCenterPointByScene(mogoMapUIController, Scene.AIMLESS); + } + + public void clear() { + topMotionLayout = null; + remainTimeGroup = null; + remainDistanceGroup = null; + arriveTimeGroup = null; + naviBg = null; + ivTurnIcon = null; + tvNextDistance = null; + tvNextRoad = null; + tvNextDistanceUnit = null; + tvTurnInfo = null; + topContainerNoLinkage = null; + cameraMode = null; + transition = null; + } +} diff --git a/modules/mogo-module-extensions/src/main/res/drawable-ldpi/module_ext_icon_seek_help_notice_icon.png b/modules/mogo-module-extensions/src/main/res/drawable-ldpi/module_ext_icon_seek_help_notice_icon.png new file mode 100644 index 0000000000..df529f009a Binary files /dev/null and b/modules/mogo-module-extensions/src/main/res/drawable-ldpi/module_ext_icon_seek_help_notice_icon.png differ diff --git a/modules/mogo-module-extensions/src/main/res/drawable-mdpi/module_ext_icon_seek_help_notice_icon.png b/modules/mogo-module-extensions/src/main/res/drawable-mdpi/module_ext_icon_seek_help_notice_icon.png new file mode 100644 index 0000000000..df529f009a Binary files /dev/null and b/modules/mogo-module-extensions/src/main/res/drawable-mdpi/module_ext_icon_seek_help_notice_icon.png differ diff --git a/modules/mogo-module-extensions/src/main/res/drawable-xhdpi/module_ext_icon_seek_help_notice_icon.png b/modules/mogo-module-extensions/src/main/res/drawable-xhdpi/module_ext_icon_seek_help_notice_icon.png new file mode 100644 index 0000000000..d23e70cbb4 Binary files /dev/null and b/modules/mogo-module-extensions/src/main/res/drawable-xhdpi/module_ext_icon_seek_help_notice_icon.png differ diff --git a/modules/mogo-module-extensions/src/main/res/drawable/module_ext_drawable_seek_help_notice_bg.xml b/modules/mogo-module-extensions/src/main/res/drawable/module_ext_drawable_seek_help_notice_bg.xml new file mode 100644 index 0000000000..a66e635a90 --- /dev/null +++ b/modules/mogo-module-extensions/src/main/res/drawable/module_ext_drawable_seek_help_notice_bg.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/modules/mogo-module-extensions/src/main/res/layout/include_navi_info_panle.xml b/modules/mogo-module-extensions/src/main/res/layout/include_navi_info_panle.xml index 289e64c9d9..3bea94c0eb 100644 --- a/modules/mogo-module-extensions/src/main/res/layout/include_navi_info_panle.xml +++ b/modules/mogo-module-extensions/src/main/res/layout/include_navi_info_panle.xml @@ -2,7 +2,8 @@ + tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout" + > + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/mogo-module-extensions/src/main/res/layout/module_ext_layout_entrance.xml b/modules/mogo-module-extensions/src/main/res/layout/module_ext_layout_entrance.xml index 290f28af62..97b5c3903e 100644 --- a/modules/mogo-module-extensions/src/main/res/layout/module_ext_layout_entrance.xml +++ b/modules/mogo-module-extensions/src/main/res/layout/module_ext_layout_entrance.xml @@ -9,6 +9,11 @@ + + + + + + + 31px 10px + + 44px + 1060px + 100px + 30px + 34px + 20px + 40px \ No newline at end of file diff --git a/modules/mogo-module-extensions/src/main/res/values/dimens.xml b/modules/mogo-module-extensions/src/main/res/values/dimens.xml index bc7e325604..2c1cfff501 100644 --- a/modules/mogo-module-extensions/src/main/res/values/dimens.xml +++ b/modules/mogo-module-extensions/src/main/res/values/dimens.xml @@ -162,4 +162,12 @@ 14px 8px + + 25px + 25px + 16px + 56px + 18px + 10px + 22px \ No newline at end of file diff --git a/modules/mogo-module-share/src/main/java/com/mogo/module/share/manager/SeekHelpManager.kt b/modules/mogo-module-share/src/main/java/com/mogo/module/share/manager/SeekHelpManager.kt index 8eb55c6bf3..d1b6bf781b 100644 --- a/modules/mogo-module-share/src/main/java/com/mogo/module/share/manager/SeekHelpManager.kt +++ b/modules/mogo-module-share/src/main/java/com/mogo/module/share/manager/SeekHelpManager.kt @@ -170,6 +170,8 @@ object SeekHelpManager { // 接口请求成功,内部同步v2x状态,通知adas,改变自车图标 ServiceApisManager.serviceApis.statusManagerApi.setSeekHelping("ShareDialog", true) SharedPrefsMgr.getInstance(context!!).putLong("seek_help_time", System.currentTimeMillis()) + SharedPrefsMgr.getInstance(context!!).putInt("seek_help_num", 0) + isSeekHelp = true aiAssist?.speakTTSVoice("已发布求助信息,将为你通知其他车主") toast("已发布求助信息,将为你通知其他车主") diff --git a/modules/mogo-module-tanlu/src/main/java/com/mogo/module/tanlu/fragment/TanluListWindow.java b/modules/mogo-module-tanlu/src/main/java/com/mogo/module/tanlu/fragment/TanluListWindow.java index dbc96cf077..244dafdc50 100644 --- a/modules/mogo-module-tanlu/src/main/java/com/mogo/module/tanlu/fragment/TanluListWindow.java +++ b/modules/mogo-module-tanlu/src/main/java/com/mogo/module/tanlu/fragment/TanluListWindow.java @@ -602,7 +602,9 @@ public class TanluListWindow extends RelativeLayout implements IMogoMarkerClickL @Override public void onQueryRoadInfoFail(@NotNull String msg, int code) { Logger.e(TAG, "onQueryRoadInfoFail ----- msg = " + msg); - speakFailVoice(searchfaileVoiceStrings[2]); +// speakFailVoice(searchfaileVoiceStrings[2]); + speakFailVoice("未发现" + mKeywords + "附近的特殊路况"); + moveToMarcker(currentLat, currentLon); } @Override @@ -1158,14 +1160,17 @@ public class TanluListWindow extends RelativeLayout implements IMogoMarkerClickL .longitude(lon); IMogoMarker mogoAnimationMarker = mMarkerManager.addMarker(TanluConstants.MODEL_NAME, options); - mogoAnimationMarker.startScaleAnimation(0, 4f, 0, 4f, 500, new LinearInterpolator(), new OnMarkerAnimationListener() { + mogoAnimationMarker.startScaleAnimation(0, 1f, 0, 1f, 500, new LinearInterpolator(), new OnMarkerAnimationListener() { @Override public void onAnimStart() { } @Override public void onAnimEnd() { - mogoAnimationMarker.destroy(); + UiThreadHandler.postDelayed( () -> { + mogoAnimationMarker.destroy(); + }, 1_200L ); + } }); diff --git a/modules/mogo-module-tanlu/src/main/res/drawable-xhdpi/tanlu_circle_image.png b/modules/mogo-module-tanlu/src/main/res/drawable-xhdpi/tanlu_circle_image.png index 4b3c40856e..32847b095d 100644 Binary files a/modules/mogo-module-tanlu/src/main/res/drawable-xhdpi/tanlu_circle_image.png and b/modules/mogo-module-tanlu/src/main/res/drawable-xhdpi/tanlu_circle_image.png differ diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XPushLiveCarScenario.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XPushLiveCarScenario.java index 524a02cf2b..89c7440c77 100644 --- a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XPushLiveCarScenario.java +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XPushLiveCarScenario.java @@ -48,25 +48,25 @@ public class V2XPushLiveCarScenario extends AbsV2XScenario @Override public void init(@Nullable V2XMessageEntity v2XMessageEntity) { - boolean isWindowShow = V2XServiceManager.getMoGoV2XStatusManager().isLeftLiveVideoShow(); - if (isWindowShow) { - close(); - } - setV2XMessageEntity(v2XMessageEntity); - if (v2XMessageEntity != null && - (v2XMessageEntity.getContent().getVideoSn() != null || - !TextUtils.isEmpty(v2XMessageEntity.getContent().getVideoUrl()))) { - show(); + if (!isSameScenario(v2XMessageEntity) + && V2XServiceManager.getMoGoStatusManager().isMainPageLaunched()) { + boolean isWindowShow = V2XServiceManager.getMoGoV2XStatusManager().isLeftLiveVideoShow(); + if (isWindowShow) { + close(); + } + setV2XMessageEntity(v2XMessageEntity); + if (v2XMessageEntity != null && + (v2XMessageEntity.getContent().getVideoSn() != null || + !TextUtils.isEmpty(v2XMessageEntity.getContent().getVideoUrl()))) { + show(); + } else { + TipToast.shortTip("附近没有可直播车机"); + Logger.e(V2XConst.MODULE_NAME, "直播地址为null"); + } } else { - TipToast.shortTip("附近没有可直播车机"); - Logger.e(V2XConst.MODULE_NAME, "直播地址为null"); + setV2XMessageEntity(v2XMessageEntity); + Logger.w(V2XConst.MODULE_NAME, "要处理的场景已经存在,丢弃这次初始化"); } -// if (!isSameScenario(v2XMessageEntity) -// && V2XServiceManager.getMoGoStatusManager().isMainPageLaunched()) { -// } else { -// setV2XMessageEntity(v2XMessageEntity); -// Logger.w(V2XConst.MODULE_NAME, "要处理的场景已经存在,丢弃这次初始化"); -// } } @Override @@ -77,21 +77,16 @@ public class V2XPushLiveCarScenario extends AbsV2XScenario @Override public void showWindow() { if (getV2XWindow() != null) { -// ViewGroup.LayoutParams layoutParams = -// new ViewGroup.LayoutParams( -// ViewGroup.LayoutParams.MATCH_PARENT, -// (int) V2XUtils.getApp().getResources().getDimension(R.dimen.module_v2x_event_window_height)); -// V2XServiceManager -// .getMogoTopViewManager() -// .addView(getV2XWindow().getView(), layoutParams, this); -// getV2XWindow().show(getV2XMessageEntity().getContent()); -// V2XServiceManager.getMoGoV2XStatusManager().setLiveCarWindowShow(TAG, true); - + ViewGroup.LayoutParams layoutParams = + new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + (int) V2XUtils.getApp().getResources() + .getDimension(R.dimen.v2x_video_window_height)); V2XServiceManager - .getIMogoWindowManager() - .addView(getV2XWindow().getView(), 0, 0, false); + .getMogoTopViewManager() + .addViewNoLinkage(getV2XWindow().getView(), layoutParams, this); getV2XWindow().show(getV2XMessageEntity().getContent()); - V2XServiceManager.getMoGoV2XStatusManager().setV2XAnimationWindowShow(TAG, true); + V2XServiceManager.getMoGoV2XStatusManager().setLiveCarWindowShow(TAG, true); } } diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XPushLiveCarWindow.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XPushLiveCarWindow.java index 0b31e6ca8c..5943f0d32a 100644 --- a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XPushLiveCarWindow.java +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XPushLiveCarWindow.java @@ -70,8 +70,8 @@ public class V2XPushLiveCarWindow extends RelativeLayout implements IV2XWindow { //移除窗体 V2XServiceManager - .getIMogoWindowManager() - .removeView(this); + .getMogoTopViewManager() + .removeViewNoLinkage(this); }); } @@ -144,8 +144,8 @@ public class V2XPushLiveCarWindow extends RelativeLayout implements IV2XWindow v2XRoadEventEntity = v2XMessageEntity.getContent(); if (v2XRoadEventEntity != null) { - if (!isSameScenario(v2XMessageEntity) - && V2XServiceManager.getMoGoStatusManager().isMainPageLaunched()) { + if (v2XMessageEntity.isShowState()) { mV2XRoadLiveCarScenario.setV2XWindow(new V2XRoadLiveCarWindow()); setV2XMessageEntity(v2XMessageEntity); show(); } else { - setV2XMessageEntity(v2XMessageEntity); - Logger.w(V2XConst.MODULE_NAME, "要处理的场景已经存在,丢弃这次初始化"); + close(); } - - } else { - close(); - } } catch (Exception e) { e.printStackTrace(); @@ -78,11 +73,16 @@ public class V2XRoadLiveCarScenario extends AbsV2XScenario + android:layout_height="wrap_content" + android:background="@drawable/v2x_alert_window_bg" + android:clipToPadding="false"> + app:layout_constraintTop_toTopOf="parent" + app:roundLayoutRadius="@dimen/dp_30" /> + + android:layout_height="@dimen/v2x_video_window_height_content" + android:clipToPadding="false"> 460px + 464px 474px - + diff --git a/modules/mogo-module-v2x/src/main/res/values-mdpi/dimens.xml b/modules/mogo-module-v2x/src/main/res/values-mdpi/dimens.xml index f3a326f52a..33f9e7b3ae 100644 --- a/modules/mogo-module-v2x/src/main/res/values-mdpi/dimens.xml +++ b/modules/mogo-module-v2x/src/main/res/values-mdpi/dimens.xml @@ -106,6 +106,7 @@ 460px + 464px 474px diff --git a/modules/mogo-module-v2x/src/main/res/values-xhdpi/dimens.xml b/modules/mogo-module-v2x/src/main/res/values-xhdpi/dimens.xml index f3f01b22e6..8968abfbcb 100644 --- a/modules/mogo-module-v2x/src/main/res/values-xhdpi/dimens.xml +++ b/modules/mogo-module-v2x/src/main/res/values-xhdpi/dimens.xml @@ -103,6 +103,7 @@ 830px + 664px 674px diff --git a/services/mogo-service-api/src/main/java/com/mogo/service/windowview/IMogoTopViewManager.java b/services/mogo-service-api/src/main/java/com/mogo/service/windowview/IMogoTopViewManager.java index 81e7550c91..f76f75b384 100644 --- a/services/mogo-service-api/src/main/java/com/mogo/service/windowview/IMogoTopViewManager.java +++ b/services/mogo-service-api/src/main/java/com/mogo/service/windowview/IMogoTopViewManager.java @@ -42,6 +42,40 @@ public interface IMogoTopViewManager extends IProvider { void addView(View view, ViewGroup.LayoutParams params, IMogoTopViewStatusListener statusListener); + + /** + * 在1/2屏添加一个view,如果没显示,会有动画 + * 给了一个默认的LayoutParams(MatchParent,dp_350) + * + * @param view 增加的view + */ + void addViewNoLinkage(View view); + + /** + * 在1/2屏添加一个view,如果没显示,会有动画,可通过设置监听,来监听增加的view的状态 + * 给了一个默认的LayoutParams(MatchParent,dp_350) + * + * @param statusListener 状态监听 + * @param view 增加的view + */ + void addViewNoLinkage(View view, IMogoTopViewStatusListener statusListener); + + /** + * 在1/2屏添加一个view,如果没显示,会有动画 + * @param view 增加的view + * @param params 相关参数 + */ + void addViewNoLinkage(View view, ViewGroup.LayoutParams params); + + /** + * 在1/2屏添加一个view,如果没显示,会有动画,可通过设置监听,来监听增加的view的状态,与其他控件没有联动 + * @param view 增加的view + * @param params 相关参数 + * @param statusListener 状态监听 + */ + void addViewNoLinkage(View view, ViewGroup.LayoutParams params, + IMogoTopViewStatusListener statusListener); + /** * 在1/2屏添加一个sub view,叠加在主view上面显示 * 给了一个默认的LayoutParams(MatchParent,dp_350) @@ -65,6 +99,12 @@ public interface IMogoTopViewManager extends IProvider { */ void removeView(View view); + /** + * 移除view,如果是最后一个view,会有移除动画 + * @param view 待移除的 view + */ + void removeViewNoLinkage(View view); + /** * 移除sub view * @param view 待移除的sub view @@ -77,4 +117,11 @@ public interface IMogoTopViewManager extends IProvider { * @return true-已经添加 false-未添加 */ boolean isViewAdded(View view); + + /** + * 这个view是否已经被添加进了顶部布局 + * @param view 待查询的view + * @return true-已经添加 false-未添加 + */ + boolean isViewNoLinkageAdded(View view); }