添加上滑fling隐藏顶部view接口及实现

This commit is contained in:
tongchenfei
2020-05-27 15:44:56 +08:00
parent 76eb4eaca5
commit 3f1408510e
7 changed files with 257 additions and 38 deletions

View File

@@ -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);

View File

@@ -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();
}
}

View File

@@ -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<View> viewCaches = new ArrayList<>();
private Map<View, IMogoTopViewStatusListener> 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);
}
}

View File

@@ -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