From 25656e83a89976cb028cfeac809c733d0bd19c26 Mon Sep 17 00:00:00 2001 From: crimean Date: Sun, 24 Mar 2019 21:48:26 +0300 Subject: [PATCH] Route details almost done --- .../res/layout/fragment_show_all_routes.xml | 1 + .../osmand/plus/base/ContextMenuFragment.java | 88 +++++++++++--- .../ChooseRouteFragment.java | 43 +++++-- .../RouteDetailsFragment.java | 110 +++++++++++++++++- .../routepreparationmenu/cards/BaseCard.java | 9 ++ .../cards/PublicTransportCard.java | 3 + 6 files changed, 225 insertions(+), 29 deletions(-) diff --git a/OsmAnd/res/layout/fragment_show_all_routes.xml b/OsmAnd/res/layout/fragment_show_all_routes.xml index 98aaaa6490..4e22b7cda9 100644 --- a/OsmAnd/res/layout/fragment_show_all_routes.xml +++ b/OsmAnd/res/layout/fragment_show_all_routes.xml @@ -7,6 +7,7 @@ android:background="@color/color_transparent"> minimumVelocity) && currentY != fullScreenTopPosY) { scroller.abortAnimation(); scroller.fling(0, currentY, 0, initialVelocity, 0, 0, - Math.min(viewHeight - menuFullHeightMax, fullScreenTopPosY), + Math.min(getMinY(), fullScreenTopPosY), screenHeight, 0, 0); currentY = scroller.getFinalY(); @@ -363,6 +377,52 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment { return view; } + public float getToolbarAlpha(int y) { + float a = 0; + if (portrait) { + if (y < bottomToolbarPosY) { + a = 1f - (y - topToolbarPosY) * (1f / (bottomToolbarPosY - topToolbarPosY)); + } + if (a < 0) { + a = 0; + } else if (a > 1) { + a = 1; + } + } + return a; + } + + public void updateToolbarVisibility(View view) { + updateToolbarVisibility(view, getViewY()); + } + + public void updateToolbarVisibility(View view, int y) { + float a = getToolbarAlpha(y); + updateVisibility(view, a); + } + + public void updateVisibility(View v, float alpha) { + boolean visible = alpha > 0; + v.setAlpha(alpha); + if (visible && v.getVisibility() != View.VISIBLE) { + v.setVisibility(View.VISIBLE); + } else if (!visible && v.getVisibility() == View.VISIBLE) { + v.setVisibility(View.INVISIBLE); + } + } + + public void updateVisibility(View v, boolean visible) { + if (visible && v.getVisibility() != View.VISIBLE) { + v.setVisibility(View.VISIBLE); + } else if (!visible && v.getVisibility() == View.VISIBLE) { + v.setVisibility(View.INVISIBLE); + } + } + + public int getMinY() { + return viewHeight - menuFullHeightMax - (portrait ? getToolbarHeight() : 0); + } + private int addStatusBarHeightIfNeeded(int res) { MapActivity mapActivity = getMapActivity(); if (Build.VERSION.SDK_INT >= 21 && mapActivity != null) { @@ -461,7 +521,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment { return (int) mainView.getY(); } - private void setViewY(int y, boolean animated, boolean adjustMapPos) { + protected void setViewY(int y, boolean animated, boolean adjustMapPos) { mainView.setY(y); ContextMenuFragmentListener listener = this.listener; if (listener != null) { @@ -505,7 +565,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment { } } - private int getMenuStatePosY(int menuState) { + public int getMenuStatePosY(int menuState) { if (!portrait) { return topScreenPosY; } @@ -543,7 +603,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment { } } - private void changeMenuState(int currentY, boolean slidingUp, boolean slidingDown, boolean animated) { + protected void changeMenuState(int currentY, boolean slidingUp, boolean slidingDown, boolean animated) { boolean needCloseMenu = false; int currentMenuState = getCurrentMenuState(); @@ -629,7 +689,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment { break; case MenuState.FULL_SCREEN: if (currentY != CURRENT_Y_UNDEFINED) { - int maxPosY = viewHeight - menuFullHeightMax; + int maxPosY = getMinY(); int minPosY = getMenuStatePosY(MenuState.FULL_SCREEN); if (maxPosY > minPosY) { maxPosY = minPosY; @@ -662,14 +722,13 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment { } } - private void applyPosY(final int currentY, final boolean needCloseMenu, boolean needMapAdjust, - final int previousMenuState, final int newMenuState, int dZoom, boolean animated) { + protected void applyPosY(final int currentY, final boolean needCloseMenu, boolean needMapAdjust, + final int previousMenuState, final int newMenuState, int dZoom, final boolean animated) { final int posY = getPosY(currentY, needCloseMenu, previousMenuState); if (getViewY() != posY || dZoom != 0) { if (posY < getViewY()) { updateMainViewLayout(posY); } - if (animated) { mainView.animate().y(posY) .setDuration(ANIMATION_DURATION) @@ -708,7 +767,6 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment { } } } - ContextMenuFragmentListener listener = this.listener; if (listener != null) { listener.onContextMenuYPosChanged(this, posY, true); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java index 14276b1f41..4b61772f7c 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java @@ -1,6 +1,8 @@ package net.osmand.plus.routepreparationmenu; import android.Manifest; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.content.Intent; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -17,10 +19,12 @@ import android.support.v4.view.ViewPager; import android.support.v7.view.ContextThemeWrapper; import android.text.Html; import android.text.TextUtils; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageButton; @@ -118,10 +122,13 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe if (!portrait) { initialMenuState = MenuState.FULL_SCREEN; solidToolbarView.setLayoutParams(new FrameLayout.LayoutParams(AndroidUtils.dpToPx(mapActivity, 345f), ViewGroup.LayoutParams.WRAP_CONTENT)); + solidToolbarView.setVisibility(View.VISIBLE); + final TypedValue typedValueAttr = new TypedValue(); + mapActivity.getTheme().resolveAttribute(R.attr.left_menu_view_bg, typedValueAttr, true); + view.findViewById(R.id.pager_container).setBackgroundResource(typedValueAttr.resourceId); view.setLayoutParams(new FrameLayout.LayoutParams(getResources().getDimensionPixelSize(R.dimen.dashboard_land_width), ViewGroup.LayoutParams.MATCH_PARENT)); } viewPager.setClipToPadding(false); - //viewPager.setPageMargin(-60); final RoutesPagerAdapter pagerAdapter = new RoutesPagerAdapter(getChildFragmentManager(), publicTransportMode ? routes.size() : 1, initialMenuState); viewPager.setAdapter(pagerAdapter); viewPager.setCurrentItem(routeIndex); @@ -608,14 +615,32 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe } } - public void updateToolbars(@NonNull ContextMenuFragment fragment, int y) { - MapActivity mapActivity = getMapActivity(); + public void updateToolbars(@NonNull final ContextMenuFragment fragment, int y, boolean animated) { + final MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { - View solidToolbarView = this.solidToolbarView; - if (solidToolbarView != null) { - solidToolbarView.setVisibility(y - fragment.getTopShadowMargin() <= solidToolbarHeight ? View.VISIBLE : View.GONE); + final View solidToolbarView = this.solidToolbarView; + if (solidToolbarView != null && portrait) { + if (animated) { + final float toolbarAlpha = fragment.getToolbarAlpha(y); + if (toolbarAlpha > 0) { + fragment.updateVisibility(solidToolbarView, true); + } + solidToolbarView.animate().alpha(toolbarAlpha) + .setDuration(ContextMenuFragment.ANIMATION_DURATION) + .setInterpolator(new DecelerateInterpolator()) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + fragment.updateVisibility(solidToolbarView, toolbarAlpha); + mapActivity.updateStatusBarColor(); + } + }) + .start(); + } else { + fragment.updateToolbarVisibility(solidToolbarView, y); + mapActivity.updateStatusBarColor(); + } } - mapActivity.updateStatusBarColor(); } } @@ -651,7 +676,7 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe @Override public void onContextMenuYPosChanged(@NonNull ContextMenuFragment fragment, int y, boolean animated) { if (fragment == getCurrentFragment()) { - updateToolbars(fragment, y); + updateToolbars(fragment, y, animated); updateZoomButtonsPos(fragment, y, animated); updateViewPager(fragment.getViewY()); } @@ -662,7 +687,6 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe LockableViewPager viewPager = this.viewPager; if (viewPager != null) { int currentItem = viewPager.getCurrentItem(); - int i = 0; List> routeDetailsFragments = this.routeDetailsFragments; for (WeakReference ref : routeDetailsFragments) { RouteDetailsFragment f = ref.get(); @@ -676,7 +700,6 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe updateViewPager(fragment.getViewY()); } } - i++; } } } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java index 7d6338fbca..06a803b5ca 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java @@ -25,6 +25,8 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.Transformation; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -93,9 +95,12 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT CardListener { public static final String ROUTE_ID_KEY = "route_id_key"; + private static final float PAGE_MARGIN = 5f; private int routeId = -1; private String destinationStreetStr = ""; + private int pageMarginPx; + private int toolbarHeightPx; private GPXFile gpx; private OrderedLineDataSet slopeDataSet; @@ -127,7 +132,7 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT @Override public int getToolbarHeight() { - return getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar); + return toolbarHeightPx; } @Override @@ -142,11 +147,17 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + Bundle args = getArguments(); + if (args != null) { + routeId = args.getInt(ROUTE_ID_KEY); + } + pageMarginPx = dpToPx(PAGE_MARGIN); + toolbarHeightPx = getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar); + View view = super.onCreateView(inflater, container, savedInstanceState); if (view != null) { - Bundle args = getArguments(); - if (args != null) { - routeId = args.getInt(ROUTE_ID_KEY); + if (isPortrait()) { + view.findViewById(getBottomScrollViewId()).setBackgroundDrawable(null); } updateCards(view); runLayoutListener(); @@ -159,6 +170,96 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT return transportCard; } + @Override + protected void changeMenuState(int currentY, boolean slidingUp, boolean slidingDown, boolean animated) { + super.changeMenuState(currentY, slidingUp, slidingDown, animated); + View mainView = getMainView(); + if (mainView != null && isPortrait()) { + final LinearLayout cardsContainer = (LinearLayout) mainView.findViewById(R.id.route_menu_cards_container); + final FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) cardsContainer.getLayoutParams(); + final int currentMenuState = getCurrentMenuState(); + if (animated) { + final int marginStart = layoutParams.leftMargin; + final int marginEnd = currentMenuState == MenuState.HEADER_ONLY ? pageMarginPx : 0; + if (marginStart != marginEnd) { + Animation a = new Animation() { + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + int margin = marginStart + (int) ((marginEnd - marginStart) * interpolatedTime); + layoutParams.setMargins(margin, 0, margin, 0); + cardsContainer.setLayoutParams(layoutParams); + } + }; + a.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + updateCardsLayout(); + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + a.setDuration(ANIMATION_DURATION); + cardsContainer.startAnimation(a); + } + } else { + updateCardsLayout(); + } + } + } + + private void updateCardsLayout() { + View mainView = getMainView(); + if (mainView != null) { + LinearLayout cardsContainer = (LinearLayout) mainView.findViewById(R.id.route_menu_cards_container); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) cardsContainer.getLayoutParams(); + if (getCurrentMenuState() == MenuState.HEADER_ONLY) { + layoutParams.setMargins(pageMarginPx, 0, pageMarginPx, 0); + AndroidUtils.setBackground(mainView.getContext(), cardsContainer, isNightMode(), R.drawable.travel_card_bg_light, R.drawable.travel_card_bg_dark); + mainView.setBackgroundDrawable(null); + } else { + layoutParams.setMargins(0, 0, 0, 0); + cardsContainer.setBackgroundDrawable(null); + AndroidUtils.setBackground(mainView.getContext(), mainView, isNightMode(), R.drawable.bg_map_context_menu_light, R.drawable.bg_map_context_menu_dark); + } + cardsContainer.setLayoutParams(layoutParams); + } + } + + @Override + protected void setViewY(int y, boolean animated, boolean adjustMapPos) { + super.setViewY(y, animated, adjustMapPos); + View mainView = getMainView(); + if (mainView != null && isPortrait()) { + int headerOnlyY = getMenuStatePosY(MenuState.HEADER_ONLY); + int halfScreenY = getMenuStatePosY(MenuState.HALF_SCREEN); + float margin = 0; + if (y > headerOnlyY) { + margin = PAGE_MARGIN; + } else if (y > halfScreenY) { + margin = PAGE_MARGIN * (1f - (float)(headerOnlyY - y) / (headerOnlyY - halfScreenY)); + } + int marginPx = dpToPx(margin); + LinearLayout cardsContainer = (LinearLayout) mainView.findViewById(R.id.route_menu_cards_container); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) cardsContainer.getLayoutParams(); + if (layoutParams.leftMargin != marginPx) { + layoutParams.setMargins(marginPx, 0, marginPx, 0); + } + if (y > halfScreenY) { + AndroidUtils.setBackground(mainView.getContext(), cardsContainer, isNightMode(), R.drawable.travel_card_bg_light, R.drawable.travel_card_bg_dark); + mainView.setBackgroundDrawable(null); + } else { + cardsContainer.setBackgroundDrawable(null); + AndroidUtils.setBackground(mainView.getContext(),mainView, isNightMode(), R.drawable.bg_map_context_menu_light, R.drawable.bg_map_context_menu_dark); + } + } + } + private void updateCards(@NonNull View view) { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { @@ -176,6 +277,7 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT card.setShowTopShadow(false); card.setShowBottomShadow(false); card.setShowDivider(false); + card.setTransparentBackground(true); card.setTransportCardListener(this); card.setListener(this); transportCard = card; diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java index 9087e6d3f8..1b7e77f24f 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java @@ -25,6 +25,7 @@ public abstract class BaseCard { boolean showTopShadow; boolean showBottomShadow; boolean showDivider = true; + boolean transparentBackground; protected boolean nightMode; private CardListener listener; @@ -122,4 +123,12 @@ public abstract class BaseCard { public void setShowDivider(boolean showDivider) { this.showDivider = showDivider; } + + public boolean isTransparentBackground() { + return transparentBackground; + } + + public void setTransparentBackground(boolean transparentBackground) { + this.transparentBackground = transparentBackground; + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/PublicTransportCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/PublicTransportCard.java index aa29d39b5b..f0a4c9237d 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/PublicTransportCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/PublicTransportCard.java @@ -144,6 +144,9 @@ public class PublicTransportCard extends BaseCard { view.findViewById(R.id.bottom_shadow).setVisibility(showBottomShadow ? View.VISIBLE : View.GONE); view.findViewById(R.id.card_divider).setVisibility(showTopShadow ? View.VISIBLE : View.GONE); view.findViewById(R.id.top_divider).setVisibility(!showTopShadow && showDivider ? View.VISIBLE : View.GONE); + if (transparentBackground) { + view.findViewById(R.id.routes_info_container).setBackgroundDrawable(null); + } } public int getRouteId() {