From 3f1408510ee49ad14da7e642653ad006eeb9b194 Mon Sep 17 00:00:00 2001 From: tongchenfei Date: Wed, 27 May 2020 15:44:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=8A=E6=BB=91fling?= =?UTF-8?q?=E9=9A=90=E8=97=8F=E9=A1=B6=E9=83=A8view=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=8F=8A=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../extensions/entrance/EntranceFragment.java | 24 +++- .../mogo/module/extensions/navi/TopView.java | 64 +++++++++ .../extensions/utils/TopViewAnimHelper.java | 126 ++++++++++++++---- .../extensions/utils/TopViewManager.java | 17 ++- .../res/layout/module_ext_layout_entrance.xml | 16 ++- .../windowview/IMogoTopViewManager.java | 26 +++- .../IMogoTopViewStatusListener.java | 22 +++ 7 files changed, 257 insertions(+), 38 deletions(-) create mode 100644 modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/navi/TopView.java create mode 100644 services/mogo-service-api/src/main/java/com/mogo/service/windowview/IMogoTopViewStatusListener.java 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 5bf3a1c9ae..9197e52aef 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 @@ -41,6 +41,7 @@ import com.mogo.module.extensions.ExtensionsModuleConst; import com.mogo.module.extensions.R; import com.mogo.module.extensions.navi.NaviInfoView; import com.mogo.module.extensions.utils.TopViewAnimHelper; +import com.mogo.module.extensions.utils.TopViewManager; import com.mogo.module.share.ShareControl; import com.mogo.service.IMogoServiceApis; import com.mogo.service.MogoServicePaths; @@ -53,6 +54,7 @@ import com.mogo.service.module.IMogoRegisterCenter; import com.mogo.service.statusmanager.IMogoStatusChangedListener; import com.mogo.service.statusmanager.IMogoStatusManager; import com.mogo.service.statusmanager.StatusDescriptor; +import com.mogo.service.windowview.IMogoTopViewStatusListener; import com.mogo.utils.ResourcesHelper; import com.mogo.utils.UiThreadHandler; import com.mogo.utils.logger.Logger; @@ -170,6 +172,8 @@ public class EntranceFragment extends MvpFragment< EntranceView, EntrancePresent private Rect mDisplayOverviewBounds; + private boolean toggle = false; + private Runnable mLockCarRunnable = new Runnable() { @Override public void run() { @@ -206,9 +210,19 @@ public class EntranceFragment extends MvpFragment< EntranceView, EntrancePresent // // todo 测试动画 // View v = LayoutInflater.from(getContext()).inflate(R.layout.demo_top, null); // TextView tv = v.findViewById(R.id.tvIndex); -// tv.setText(demoCache.size() + ""); +// tv.setText(demoCache.size() + ": " + v); // demoCache.add(v); -// mApis.getTopViewManager().addView(v); +// mApis.getTopViewManager().addView(v, new IMogoTopViewStatusListener() { +// @Override +// public void onViewAdded(View view) { +// Logger.d(TAG, "onViewAdded: " + view); +// } +// +// @Override +// public void onViewRemoved(View view) { +// Logger.d(TAG, "onViewRemoved: " + view); +// } +// }); // 原始逻辑 isClickShare = true; if ( mIMogoAuthorizeModuleManager.needAuthorize( AUTHORIZE_TYPE_LAUNCHER_SHARE ) ) { @@ -237,6 +251,12 @@ public class EntranceFragment extends MvpFragment< EntranceView, EntrancePresent mMove2CurrentLocation = findViewById( R.id.module_entrance_id_move2_current_location ); mMove2CurrentLocation.setOnClickListener( view -> { // // todo 测试动画 +// if(!toggle) { +// TopViewAnimHelper.getInstance().showNaviView(); +// }else{ +// TopViewAnimHelper.getInstance().hideNaviView(); +// } +// toggle = !toggle; // if(demoCache.size()>0) { // View v = demoCache.remove(demoCache.size() - 1); // boolean isViewAdded = mApis.getTopViewManager().isViewAdded(v); diff --git a/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/navi/TopView.java b/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/navi/TopView.java new file mode 100644 index 0000000000..8e13c5bd79 --- /dev/null +++ b/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/navi/TopView.java @@ -0,0 +1,64 @@ +package com.mogo.module.extensions.navi; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.ViewConfiguration; +import android.widget.FrameLayout; + +/** + * 顶部view封装,用于处理手指滑动 + */ +public class TopView extends FrameLayout { + public TopView(Context context) { + super(context); + } + + public TopView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public TopView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + private OnTopViewSlideListener slideListener; + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP) { + // 简单处理,只要手指抬起的位置在按下的位置上面(就是手指上划),就触发外面的动画 + if (event.getY() < originY) { + if (slideListener != null) { + slideListener.onSlideUp(); + } + return true; + } + } + return super.onTouchEvent(event); + } + + private float originY; + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + originY = ev.getY(); + } else if (ev.getAction() == MotionEvent.ACTION_MOVE) { + // 垂直滑动,事件拦截 + return Math.abs(originY - ev.getY()) > ViewConfiguration.get(getContext()).getScaledTouchSlop(); + } + return false; + } + + public void setSlideListener(OnTopViewSlideListener slideListener) { + this.slideListener = slideListener; + } + + public interface OnTopViewSlideListener{ + /** + * 监听到view上滑 + */ + void onSlideUp(); + } +} diff --git a/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/utils/TopViewAnimHelper.java b/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/utils/TopViewAnimHelper.java index 8f593faa22..68d8a2bfe4 100644 --- a/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/utils/TopViewAnimHelper.java +++ b/modules/mogo-module-extensions/src/main/java/com/mogo/module/extensions/utils/TopViewAnimHelper.java @@ -1,13 +1,12 @@ package com.mogo.module.extensions.utils; import android.animation.Animator; -import android.animation.ObjectAnimator; import android.transition.AutoTransition; import android.transition.Transition; import android.transition.TransitionManager; +import android.util.ArrayMap; import android.view.View; import android.view.ViewGroup; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -19,10 +18,13 @@ import com.mogo.map.uicontroller.IMogoMapUIController; import com.mogo.module.common.map.MapCenterPointStrategy; import com.mogo.module.common.map.Scene; 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; /** @@ -34,13 +36,15 @@ public class TopViewAnimHelper { private static final String TAG = "TopViewAnimHelper"; private ConstraintLayout topMotionLayout; - private Group naviGroup, remainTimeGroup, remainDistanceGroup, arriveTimeGroup; + private Group remainTimeGroup, remainDistanceGroup, arriveTimeGroup; private View naviBg; private ImageView ivTurnIcon; private TextView tvNextDistance; private TextView tvNextRoad; - private FrameLayout topContainer; + private TextView tvNextDistanceUnit; + private TextView tvTurnInfo; + private TopView topContainer; private ConstraintSet constraintSet = new ConstraintSet(); private Transition transition = new AutoTransition(); @@ -75,11 +79,14 @@ public class TopViewAnimHelper { public void init(ConstraintLayout rootView, OnTopViewAnimSimpleListener listener) { topMotionLayout = rootView; naviBg = rootView.findViewById(R.id.module_map_id_navi_bg); - naviGroup = rootView.findViewById(R.id.naviGroup); remainTimeGroup = rootView.findViewById(R.id.remainTimeGroup); remainDistanceGroup = rootView.findViewById(R.id.remainDistanceGroup); arriveTimeGroup = rootView.findViewById(R.id.arriveTimeGroup); topContainer = rootView.findViewById(R.id.module_entrance_id_top_container); + 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); + + topContainer.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); @@ -102,6 +109,16 @@ public class TopViewAnimHelper { if (listener != null) { listener.onAnimEnd(); } + Logger.d(TAG, "onTransitionEnd: " + currentAnimatingView); + IMogoTopViewStatusListener listener; + if (isTopViewOut) { + listener = statusListenerMap.remove(currentAnimatingView); + }else{ + listener = statusListenerMap.get(currentAnimatingView); + } + if (listener != null) { + listener.onViewAdded(currentAnimatingView); + } } @Override @@ -125,8 +142,11 @@ public class TopViewAnimHelper { private boolean isTopViewOut = true; private List viewCaches = new ArrayList<>(); + private Map statusListenerMap = new ArrayMap<>(); - public void startTopInAnim(View view, ViewGroup.LayoutParams params) { + private View currentAnimatingView = null; + + public void startTopInAnim(View view, ViewGroup.LayoutParams params, IMogoTopViewStatusListener statusListener) { Logger.d(TAG, "startTopInAnim====="+isTopViewOut); if (view == null) { throw new IllegalArgumentException("method addTopView params view is null"); @@ -136,6 +156,7 @@ public class TopViewAnimHelper { } if (!viewCaches.contains(view)) { // 判断此view是否已经增加到了顶部view,如果增加过就不增加了 + statusListenerMap.put(view, statusListener); Logger.d(TAG, "开始执行"); isTopViewOut = false; if (topContainer.getChildCount() > 0) { @@ -145,11 +166,42 @@ public class TopViewAnimHelper { topContainer.addView(view, params); Logger.d(TAG, "顶部view已经有布局了,增加新增view滑入动画: " + view.getTranslationY() + " height:" + " " + view.getHeight() + " paramsHeight: " + params.height); - view.animate().translationY(0).setDuration(500).start(); + 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); topContainer.addView(view, params); + + if (naviBg.getVisibility() == View.VISIBLE) { + remainDistanceGroup.setVisibility(View.GONE); + remainTimeGroup.setVisibility(View.GONE); + arriveTimeGroup.setVisibility(View.GONE); + } + constraintSet.clone(topMotionLayout); constraintSet.clear(R.id.module_entrance_id_top_container,ConstraintSet.BOTTOM); @@ -157,7 +209,7 @@ public class TopViewAnimHelper { R.id.module_entrance_id_top_motion_layout, ConstraintSet.TOP); TransitionManager.beginDelayedTransition(topMotionLayout, transition); checkCameraModePosition(false); - if (naviGroup.getVisibility() == View.VISIBLE) { + if (naviBg.getVisibility() == View.VISIBLE) { // 约束设置需要在applyTo()方法之前执行,visiable设置需要在applyTo() // 方法之后执行才能生效,所以分开了两个判断,至于为什么这么做才能生效,不得而知 constraintSet.connect(tvNextDistance.getId(), ConstraintSet.BOTTOM, @@ -170,11 +222,6 @@ public class TopViewAnimHelper { (int) topMotionLayout.getContext().getResources().getDimension(R.dimen.dp_46)); } constraintSet.applyTo(topMotionLayout); - if (naviGroup.getVisibility() == View.VISIBLE) { - remainDistanceGroup.setVisibility(View.GONE); - remainTimeGroup.setVisibility(View.GONE); - arriveTimeGroup.setVisibility(View.GONE); - } ivTurnIcon.getLayoutParams().height = (int) getDimen(R.dimen.module_ext_navi_info_panel_turn_icon_small_height); ivTurnIcon.getLayoutParams().width = @@ -182,7 +229,7 @@ public class TopViewAnimHelper { naviBg.getLayoutParams().height = (int) topMotionLayout.getContext().getResources().getDimension(R.dimen.module_ext_navi_info_panel_small_height); int scene = 0; - if(naviGroup.getVisibility() == View.VISIBLE){ + if(naviBg.getVisibility() == View.VISIBLE){ scene = Scene.NAVI_WITH_ROAD_EVENT; }else{ scene = Scene.AIMLESS_WITH_ROAD_EVENT; @@ -193,6 +240,15 @@ public class TopViewAnimHelper { } } + /** + * 退出最新的(也就是最上面的)view + */ + private void startLatestTopOutAnim(){ + if (topContainer.getChildCount() > 0) { + startTopOutAnim(topContainer.getChildAt(topContainer.getChildCount() - 1)); + } + } + public void startTopOutAnim(View view) { Logger.d("TopViewAnimHelper", "startTopOutAnim====="); if (!isTopViewOut) { @@ -208,8 +264,15 @@ public class TopViewAnimHelper { @Override public void onAnimationEnd(Animator animation) { + Logger.d(TAG,"onAnimationEnd: "+view); viewCaches.remove(view); topContainer.removeView(view); + IMogoTopViewStatusListener listener = statusListenerMap.remove(view); + if (listener != null) { + listener.onViewRemoved(view); + }else{ + Logger.d(TAG, "listener is null"); + } } @Override @@ -225,7 +288,13 @@ public class TopViewAnimHelper { }).start(); }else { // 顶部view仅剩一个view,需要整体上移 + currentAnimatingView = view; isTopViewOut = true; + if (naviBg.getVisibility() == View.VISIBLE) { + remainDistanceGroup.setVisibility(View.VISIBLE); + remainTimeGroup.setVisibility(View.VISIBLE); + arriveTimeGroup.setVisibility(View.VISIBLE); + } constraintSet.clone(topMotionLayout); constraintSet.clear(R.id.module_entrance_id_top_container,ConstraintSet.TOP); @@ -234,7 +303,7 @@ public class TopViewAnimHelper { TransitionManager.beginDelayedTransition(topMotionLayout, transition); checkCameraModePosition(false); - if (naviGroup.getVisibility() == View.VISIBLE) { + if (naviBg.getVisibility() == View.VISIBLE) { // 约束设置需要在applyTo()方法之前执行,visiable设置需要在applyTo() // 方法之后执行才能生效,所以分开了两个判断,至于为什么这么做才能生效,不得而知 constraintSet.clear(tvNextDistance.getId(), ConstraintSet.BOTTOM); @@ -246,11 +315,7 @@ public class TopViewAnimHelper { 0); } constraintSet.applyTo(topMotionLayout); - if (naviGroup.getVisibility() == View.VISIBLE) { - remainDistanceGroup.setVisibility(View.VISIBLE); - remainTimeGroup.setVisibility(View.VISIBLE); - arriveTimeGroup.setVisibility(View.VISIBLE); - } + ivTurnIcon.getLayoutParams().height = (int) getDimen(R.dimen.module_ext_navi_info_panel_turn_icon_height); ivTurnIcon.getLayoutParams().width = @@ -258,7 +323,7 @@ public class TopViewAnimHelper { naviBg.getLayoutParams().height = (int) topMotionLayout.getContext().getResources().getDimension(R.dimen.module_ext_navi_info_panel_height); int scene = 0; - if(naviGroup.getVisibility() == View.VISIBLE){ + if(naviBg.getVisibility() == View.VISIBLE){ scene = Scene.NAVI; }else{ scene = Scene.AIMLESS; @@ -271,7 +336,7 @@ public class TopViewAnimHelper { public void showNaviView() { Logger.d("TopViewAnimHelper", "showNaviView====="); - naviGroup.setVisibility(View.VISIBLE); + setNaviVisibility(View.VISIBLE); int scene = 0; if (isTopViewOut) { remainDistanceGroup.setVisibility(View.VISIBLE); @@ -326,7 +391,7 @@ public class TopViewAnimHelper { public void hideNaviView() { Logger.d("TopViewAnimHelper", "hideNaviView====="); - naviGroup.setVisibility(View.GONE); + setNaviVisibility(View.GONE); remainDistanceGroup.setVisibility(View.GONE); remainTimeGroup.setVisibility(View.GONE); arriveTimeGroup.setVisibility(View.GONE); @@ -345,7 +410,7 @@ public class TopViewAnimHelper { if (isNeedClone) { constraintSet.clone(topMotionLayout); } - if (naviGroup.getVisibility() == View.VISIBLE) { + if (naviBg.getVisibility() == View.VISIBLE) { constraintSet.connect(cameraMode.getId(), ConstraintSet.TOP, naviBg.getId(), ConstraintSet.BOTTOM, (int) getDimen(R.dimen.dp_30)); } else { @@ -378,4 +443,17 @@ public class TopViewAnimHelper { 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); + + } } 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 bab6447d35..cd238dd6c6 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 @@ -8,6 +8,7 @@ import com.alibaba.android.arouter.facade.annotation.Route; import com.mogo.module.extensions.R; import com.mogo.service.MogoServicePaths; import com.mogo.service.windowview.IMogoTopViewManager; +import com.mogo.service.windowview.IMogoTopViewStatusListener; /** * 顶部1/2界面管理 @@ -36,12 +37,24 @@ public class TopViewManager implements IMogoTopViewManager { @Override public void addView(View view) { addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - (int) context.getResources().getDimension(R.dimen.dp_350))); + (int) context.getResources().getDimension(R.dimen.dp_350)),null); + } + + @Override + public void addView(View view, IMogoTopViewStatusListener statusListener) { + addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + (int) context.getResources().getDimension(R.dimen.dp_350)),statusListener); } @Override public void addView(View view, ViewGroup.LayoutParams params) { - TopViewAnimHelper.getInstance().startTopInAnim(view, params); + addView(view, params, null); + } + + @Override + public void addView(View view, ViewGroup.LayoutParams params, + IMogoTopViewStatusListener statusListener) { + TopViewAnimHelper.getInstance().startTopInAnim(view, params, statusListener); } @Override 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 178a974615..df539e39d5 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 @@ -6,20 +6,22 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - + + + + + +