diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java index 61e7aa129f..d25354117d 100644 --- a/android/src/com/mapswithme/maps/MwmActivity.java +++ b/android/src/com/mapswithme/maps/MwmActivity.java @@ -1174,9 +1174,6 @@ public class MwmActivity extends BaseMwmFragmentActivity Framework.nativeDeactivatePopup(); mPlacePage.setMapObject(null, false); } - - if (mNavAnimationController != null) - mNavAnimationController.onPlacePageVisibilityChanged(isVisible); } @Override @@ -1388,20 +1385,46 @@ public class MwmActivity extends BaseMwmFragmentActivity private void adjustMenuLineFrameVisibility() { final RoutingController controller = RoutingController.get(); + final int menuHeight = getCurrentMenu().getFrame().getHeight(); if (controller.isBuilt() || controller.isUberRequestHandled()) { - mMainMenu.showLineFrame(true); + mMainMenu.showLineFrame(true, new Runnable() + { + @Override + public void run() + { + adjustCompass(0); + adjustRuler(0, 0); + } + }); return; } if (controller.isPlanning() || controller.isBuilding() || controller.isErrorEncountered()) { - mMainMenu.showLineFrame(false); + mMainMenu.showLineFrame(false, new Runnable() + { + @Override + public void run() + { + adjustCompass(menuHeight); + adjustRuler(0, menuHeight); + } + }); return; } - mMainMenu.showLineFrame(true); + mMainMenu.showLineFrame(true, new Runnable() + { + @Override + public void run() + { + adjustCompass(0); + adjustRuler(0, 0); + } + }); + } private void setNavButtonsTopLimit(int limit) @@ -1415,6 +1438,8 @@ public class MwmActivity extends BaseMwmFragmentActivity @Override public void showRoutePlan(boolean show, @Nullable Runnable completionListener) { + if (mNavAnimationController != null && !mIsFragmentContainer) + mNavAnimationController.slide(show); if (show) { mSearchController.hide(); @@ -1538,7 +1563,7 @@ public class MwmActivity extends BaseMwmFragmentActivity public void animateSearchPoiTransition(@NonNull final Rect startRect, @Nullable final Runnable runnable) { - Animations.rizeTransition(mRootView, startRect, runnable); + Animations.riseTransition(mRootView, startRect, runnable); } @Override diff --git a/android/src/com/mapswithme/maps/NavigationButtonsAnimationController.java b/android/src/com/mapswithme/maps/NavigationButtonsAnimationController.java index 51c54058e8..4af215217c 100644 --- a/android/src/com/mapswithme/maps/NavigationButtonsAnimationController.java +++ b/android/src/com/mapswithme/maps/NavigationButtonsAnimationController.java @@ -1,5 +1,8 @@ package com.mapswithme.maps; +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.content.res.Resources; import android.support.annotation.NonNull; import android.view.View; @@ -7,12 +10,11 @@ import com.mapswithme.maps.routing.RoutingController; import com.mapswithme.util.Animations; import com.mapswithme.util.Config; import com.mapswithme.util.UiUtils; -import com.mapswithme.util.log.DebugLogger; class NavigationButtonsAnimationController { - private static final DebugLogger LOGGER = - new DebugLogger(NavigationButtonsAnimationController.class.getSimpleName()); + private static final int ANIM_TOGGLE = MwmApplication.get().getResources().getInteger(R.integer.anim_slots_toggle); + @NonNull private final View mZoomIn; @NonNull @@ -20,24 +22,207 @@ class NavigationButtonsAnimationController @NonNull private final View mMyPosition; - private float mBottomLimit; - private float mTopLimit; + private final float mMargin; + private float mBottom; + private float mTop; - private boolean mMyPosAnimate; + private boolean mIsZoomAnimate; + private boolean mIsMyPosAnimate; + private boolean mIsSlideDown; + + private final float mMenuHeight; NavigationButtonsAnimationController(@NonNull View zoomIn, @NonNull View zoomOut, @NonNull View myPosition) { mZoomIn = zoomIn; mZoomOut = zoomOut; - checkZoomButtonsVisibility(); + UiUtils.showIf(showZoomButtons(), mZoomIn, mZoomOut); mMyPosition = myPosition; - calculateBottomLimit(); + Resources res = mZoomIn.getResources(); + mMargin = res.getDimension(R.dimen.margin_base_plus); + mMenuHeight = res.getDimension(R.dimen.menu_line_height); + calculateLimitTranslations(); } - private void checkZoomButtonsVisibility() + private void calculateLimitTranslations() { - UiUtils.showIf(showZoomButtons(), mZoomIn, mZoomOut); + mTop = mMargin; + mMyPosition.addOnLayoutChangeListener(new View.OnLayoutChangeListener() + { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) + { + mBottom = bottom + mMargin; + mMyPosition.removeOnLayoutChangeListener(this); + } + }); + } + + void setTopLimit(float limit) + { + mTop = limit + mMargin; + update(); + } + + private void fadeOutZoom() + { + if (mIsSlideDown) + return; + mIsZoomAnimate = true; + Animations.fadeOutView(mZoomIn, new Runnable() + { + @Override + public void run() + { + mZoomIn.setVisibility(View.INVISIBLE); + mIsZoomAnimate = false; + } + }); + Animations.fadeOutView(mZoomOut, new Runnable() + { + @Override + public void run() + { + mZoomOut.setVisibility(View.INVISIBLE); + } + }); + } + + private void fadeInZoom() + { + mIsZoomAnimate = true; + mZoomIn.setVisibility(View.VISIBLE); + mZoomOut.setVisibility(View.VISIBLE); + Animations.fadeInView(mZoomIn, new Runnable() + { + @Override + public void run() + { + mIsZoomAnimate = false; + } + }); + Animations.fadeInView(mZoomOut, null); + } + + private void fadeOutMyPosition() + { + if (mIsSlideDown) + return; + + mIsMyPosAnimate = true; + Animations.fadeOutView(mMyPosition, new Runnable() + { + @Override + public void run() + { + UiUtils.invisible(mMyPosition); + mIsMyPosAnimate = false; + } + }); + } + + private void fadeInMyPosition() + { + mIsMyPosAnimate = true; + mMyPosition.setVisibility(View.VISIBLE); + Animations.fadeInView(mMyPosition, new Runnable() + { + @Override + public void run() + { + mIsMyPosAnimate = false; + } + }); + } + + void onPlacePageMoved(float translationY) + { + if (UiUtils.isLandscape(mMyPosition.getContext()) || mBottom == 0) + return; + + final float amount = mZoomIn.getTranslationY() > 0 ? mMenuHeight : 0; + final float translation = translationY - mBottom; + update(translation <= amount ? translation : amount); + } + + private void update() + { + update(mZoomIn.getTranslationY()); + } + + private void update(final float translation) + { + mMyPosition.setTranslationY(translation); + mZoomOut.setTranslationY(translation); + mZoomIn.setTranslationY(translation); + if (!mIsZoomAnimate && isOverTopLimit(mZoomIn)) + { + fadeOutZoom(); + } + else if (!mIsZoomAnimate && satisfyTopLimit(mZoomIn)) + { + fadeInZoom(); + } + + if (!shouldBeHidden() && !mIsMyPosAnimate + && isOverTopLimit(mMyPosition)) + { + fadeOutMyPosition(); + } + else if (!shouldBeHidden() && !mIsMyPosAnimate + && satisfyTopLimit(mMyPosition)) + { + fadeInMyPosition(); + } + } + + private boolean isOverTopLimit(@NonNull View view) + { + return view.getVisibility() == View.VISIBLE && view.getY() <= mTop; + } + + private boolean satisfyTopLimit(@NonNull View view) + { + return view.getVisibility() == View.INVISIBLE && view.getY() >= mTop; + } + + private boolean shouldBeHidden() + { + return LocationState.getMode() == LocationState.FOLLOW_AND_ROTATE + && (RoutingController.get().isPlanning() || RoutingController.get().isNavigating()); + } + + void slide(boolean isDown) + { + if (UiUtils.isLandscape(mMyPosition.getContext()) + || (!isDown && mZoomIn.getTranslationY() <= 0)) + return; + + mIsSlideDown = isDown; + + ValueAnimator animator = ValueAnimator.ofFloat(isDown ? 0 : mMenuHeight, isDown ? mMenuHeight : 0); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() + { + @Override + public void onAnimationUpdate(ValueAnimator animation) + { + float value = (float) animation.getAnimatedValue(); + update(value); + } + }); + animator.addListener(new UiUtils.SimpleAnimatorListener() + { + @Override + public void onAnimationEnd(Animator animation) + { + mIsSlideDown = false; + update(); + } + }); + animator.setDuration(ANIM_TOGGLE); + animator.start(); } void disappearZoomButtons() @@ -54,204 +239,8 @@ class NavigationButtonsAnimationController if (!showZoomButtons()) return; - if (!canZoomButtonsFitInScreen()) - return; - - Animations.appearSliding(mZoomIn, Animations.RIGHT, null); - Animations.appearSliding(mZoomOut, Animations.RIGHT, null); - updateZoomButtonsPosition(); - } - - void setTopLimit(float limit) - { - mTopLimit = limit; - updateZoomButtonsPosition(); - } - - void onPlacePageVisibilityChanged(boolean isVisible) - { - if (isVisible) - fadeOutZooms(); - else - fadeInZooms(); - } - - void onPlacePageMoved(float translationY) - { - if (mBottomLimit == 0) - return; - - float translation = translationY - mBottomLimit; - animateMyPosition(translation <= 0 ? translation : 0); - } - - private void calculateBottomLimit() - { - mMyPosition.addOnLayoutChangeListener(new View.OnLayoutChangeListener() - { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) - { - mBottomLimit = bottom; - mMyPosition.removeOnLayoutChangeListener(this); - } - }); - } - - private void updateZoomButtonsPosition() - { - // It means that the zoom buttons fit in screen perfectly, - // any updates of position are no needed. - if (mZoomIn.getTop() >= mTopLimit && UiUtils.isVisible(mZoomIn)) - return; - - // If the top limit is decreased we try to return zoom buttons at initial position. - if (mTopLimit < mZoomIn.getTop() && tryPlaceZoomButtonsAtInitialPosition()) - { - LOGGER.d("Zoom buttons were come back to initial position"); - return; - } - - // If top view overlaps the zoomIn button. - if (mTopLimit > mZoomIn.getTop()) - { - // We should try to pull out the zoomIn button from under the top view - // if available space allows us doing that. - if (tryPlaceZoomButtonsUnderTopLimit()) - return; - - // Otherwise, we just fade out the zoom buttons - // since there is not enough space on the screen for them. - fadeOutZooms(); - } - } - - private boolean tryPlaceZoomButtonsAtInitialPosition() - { - float availableSpace = mBottomLimit - mTopLimit; - float requiredSpace = mBottomLimit - mZoomIn.getTop() - mZoomIn.getTranslationY(); - if (requiredSpace > availableSpace) - return false; - - mZoomIn.setTranslationY(0); - mZoomOut.setTranslationY(0); - return true; - } - - private boolean tryPlaceZoomButtonsUnderTopLimit() - { - if (!canZoomButtonsFitInScreen()) - return false; - - float requiredTranslate = mTopLimit - mZoomIn.getTop(); - mZoomIn.setTranslationY(requiredTranslate); - mZoomOut.setTranslationY(requiredTranslate); - return true; - } - - private boolean canZoomButtonsFitInScreen() - { - float availableSpace = mBottomLimit - mTopLimit; - return getMinimumRequiredHeightForButtons() <= availableSpace; - } - - private float getMinimumRequiredHeightForButtons() - { - return mZoomIn.getHeight() + mZoomOut.getHeight() + mMyPosition.getHeight(); - } - - private void fadeOutZooms() - { - Animations.fadeOutView(mZoomIn, new Runnable() - { - @Override - public void run() - { - mZoomIn.setVisibility(View.INVISIBLE); - } - }); - Animations.fadeOutView(mZoomOut, new Runnable() - { - @Override - public void run() - { - mZoomOut.setVisibility(View.INVISIBLE); - } - }); - } - - private void fadeInZooms() - { - if (!showZoomButtons()) - return; - - if (!canZoomButtonsFitInScreen()) - return; - - mZoomIn.setVisibility(View.VISIBLE); - mZoomOut.setVisibility(View.VISIBLE); - Animations.fadeInView(mZoomIn, null); - Animations.fadeInView(mZoomOut, null); - } - - private void fadeOutMyPosition() - { - mMyPosAnimate = true; - Animations.fadeOutView(mMyPosition, new Runnable() - { - @Override - public void run() - { - UiUtils.invisible(mMyPosition); - mMyPosAnimate = false; - } - }); - } - - private void fadeInMyPosition() - { - mMyPosAnimate = true; - mMyPosition.setVisibility(View.VISIBLE); - Animations.fadeInView(mMyPosition, new Runnable() - { - @Override - public void run() - { - mMyPosAnimate = false; - } - }); - } - - private void animateMyPosition(float translation) - { - mMyPosition.setTranslationY(translation); - if (!shouldMyPositionBeHidden() && !mMyPosAnimate - && isOverTopLimit(mMyPosition)) - { - fadeOutMyPosition(); - } - else if (!shouldMyPositionBeHidden() && !mMyPosAnimate - && satisfyTopLimit(mMyPosition)) - { - fadeInMyPosition(); - } - } - - private boolean isOverTopLimit(@NonNull View view) - { - return view.getVisibility() == View.VISIBLE && view.getY() <= mTopLimit; - } - - private boolean satisfyTopLimit(@NonNull View view) - { - return view.getVisibility() == View.INVISIBLE && view.getY() >= mTopLimit; - } - - private boolean shouldMyPositionBeHidden() - { - return LocationState.getMode() == LocationState.FOLLOW_AND_ROTATE - && (RoutingController.get().isPlanning()); + Animations.appearSliding(mZoomIn, Animations.LEFT, null); + Animations.appearSliding(mZoomOut, Animations.LEFT, null); } private static boolean showZoomButtons() @@ -261,6 +250,6 @@ class NavigationButtonsAnimationController public void onResume() { - checkZoomButtonsVisibility(); + update(); } } diff --git a/android/src/com/mapswithme/maps/widget/menu/MainMenu.java b/android/src/com/mapswithme/maps/widget/menu/MainMenu.java index 74ae228b57..c522a265dd 100644 --- a/android/src/com/mapswithme/maps/widget/menu/MainMenu.java +++ b/android/src/com/mapswithme/maps/widget/menu/MainMenu.java @@ -1,8 +1,8 @@ package com.mapswithme.maps.widget.menu; +import android.support.annotation.Nullable; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; import android.widget.TextView; import com.mapswithme.maps.MwmActivity; @@ -11,9 +11,9 @@ import com.mapswithme.maps.R; import com.mapswithme.maps.downloader.MapManager; import com.mapswithme.maps.downloader.UpdateInfo; import com.mapswithme.maps.routing.RoutingController; +import com.mapswithme.util.Animations; import com.mapswithme.util.Graphics; import com.mapswithme.util.UiUtils; -import ru.mail.android.mytarget.core.models.Stat; import java.util.ArrayList; import java.util.HashMap; @@ -263,9 +263,9 @@ public class MainMenu extends BaseMenu { UiUtils.show(mButtonsFrame); expandContent = false; - } else + } + else { - UiUtils.showIf(state == State.MENU, mButtonsFrame); UiUtils.showIf(isRouting, mRoutePlanFrame); if (isRouting) @@ -313,8 +313,17 @@ public class MainMenu extends BaseMenu return mAnimationTrackListener; } - public void showLineFrame(boolean show) + public void showLineFrame(boolean show, @Nullable Runnable completion) { - UiUtils.showIf(show, mLineFrame); + if (show) + { + UiUtils.hide(mFrame); + Animations.appearSliding(mFrame, Animations.BOTTOM, completion); + } + else + { + UiUtils.show(mFrame); + Animations.disappearSliding(mFrame, Animations.BOTTOM, completion); + } } } diff --git a/android/src/com/mapswithme/util/Animations.java b/android/src/com/mapswithme/util/Animations.java index ad02eb9dfc..bb41b87079 100644 --- a/android/src/com/mapswithme/util/Animations.java +++ b/android/src/com/mapswithme/util/Animations.java @@ -143,7 +143,7 @@ public final class Animations }); } - public static void rizeTransition(@NonNull ViewGroup rootView, @NonNull final Rect startRect, + public static void riseTransition(@NonNull ViewGroup rootView, @NonNull final Rect startRect, @Nullable final Runnable runnable) { Context context = rootView.getContext();