diff --git a/android/res/layout/place_page_container_fragment.xml b/android/res/layout/place_page_container_fragment.xml index f53af67f3a..db75b662e4 100644 --- a/android/res/layout/place_page_container_fragment.xml +++ b/android/res/layout/place_page_container_fragment.xml @@ -4,9 +4,17 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> + mPlacePageBehavior; private NestedScrollViewClickFixed mPlacePage; private ViewGroup mPlacePageContainer; + private View mPlacePageStatusBarBackground; private ViewGroup mCoordinator; private int mViewportMinHeight; private int mButtonsHeight; private int mMaxButtons; + private int mRoutingHeaderHeight; private PlacePageViewModel mViewModel; private int mPreviewHeight; private int mFrameHeight; @@ -72,6 +76,8 @@ public class PlacePageController extends Fragment implements private ValueAnimator mCustomPeekHeightAnimator; private PlacePageRouteSettingsListener mPlacePageRouteSettingsListener; + private final Observer mPlacePageDistanceToTopObserver = this::updateStatusBarBackground; + private final BottomSheetBehavior.BottomSheetCallback mDefaultBottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() { @Override @@ -114,11 +120,13 @@ public class PlacePageController extends Fragment implements mViewportMinHeight = res.getDimensionPixelSize(R.dimen.viewport_min_height); mButtonsHeight = (int) res.getDimension(R.dimen.place_page_buttons_height); mMaxButtons = res.getInteger(R.integer.pp_buttons_max); + mRoutingHeaderHeight = (int) res.getDimension(ThemeUtils.getResource(requireContext(), R.attr.actionBarSize)); mCoordinator = activity.findViewById(R.id.coordinator); mPlacePage = view.findViewById(R.id.placepage); mPlacePageContainer = view.findViewById(R.id.placepage_container); mPlacePageBehavior = BottomSheetBehavior.from(mPlacePage); + mPlacePageStatusBarBackground = view.findViewById(R.id.place_page_status_bar_background); mShouldCollapse = true; @@ -133,6 +141,14 @@ public class PlacePageController extends Fragment implements ViewCompat.setOnApplyWindowInsetsListener(mPlacePage, (v, windowInsets) -> { mCurrentWindowInsets = windowInsets; + final Insets insets = mCurrentWindowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); + final ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) mPlacePageStatusBarBackground.getLayoutParams(); + // Layout calculations are heavy so we compute them once then move the view from behind the place page to the status bar + layoutParams.height = insets.top; + layoutParams.width = mPlacePage.getWidth(); + // Make sure the view is centered within the insets as is the place page + layoutParams.setMargins(insets.left, 0, insets.right, 0); + mPlacePageStatusBarBackground.setLayoutParams(layoutParams); return windowInsets; }); } @@ -209,14 +225,19 @@ public class PlacePageController extends Fragment implements private void setPlacePageHeightBounds() { final int peekHeight = calculatePeekHeight(); + final Insets insets = mCurrentWindowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); // Make sure the place page can reach the peek height - final int height = Math.max(peekHeight, mFrameHeight); + final int minHeight = Math.max(peekHeight, mFrameHeight); + // Prevent the place page from showing under the status bar + // If we are in planning mode, prevent going above the header + final int topInsets = insets.top + (RoutingController.get().isPlanning() ? mRoutingHeaderHeight : 0); + final int maxHeight = Math.min(minHeight + insets.bottom, mCoordinator.getHeight() - topInsets); // Set the minimum height of the place page to prevent jumps when new data results in SMALLER content // This cannot be set on the place page itself as it has the fitToContent property set - mPlacePageContainer.setMinimumHeight(height); + mPlacePageContainer.setMinimumHeight(minHeight); // Set the maximum height of the place page to prevent jumps when new data results in BIGGER content // It does not take into account the navigation bar height so we need to add it manually - mPlacePageBehavior.setMaxHeight(height + mCurrentWindowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom); + mPlacePageBehavior.setMaxHeight(maxHeight); } /** @@ -294,6 +315,7 @@ public class PlacePageController extends Fragment implements mPreviewHeight = previewHeight; mFrameHeight = frameHeight; mViewModel.setPlacePageWidth(mPlacePage.getWidth()); + mPlacePageStatusBarBackground.getLayoutParams().width = mPlacePage.getWidth(); // Make sure to update the peek height on the UI thread to prevent weird animation jumps mPlacePage.post(() -> { setPeekHeight(); @@ -568,12 +590,37 @@ public class PlacePageController extends Fragment implements close(); } + private void updateStatusBarBackground(int distanceToTop) + { + // This callback may be called before insets are updated when resuming the app + if (mCurrentWindowInsets == null) + return; + final int topInset = mCurrentWindowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top; + // Only animate the status bar background if the place page can reach it + if (mCoordinator.getHeight() - mPlacePageContainer.getHeight() < topInset) + { + final int animationStartHeight = topInset * 3; + int newHeight = 0; + if (distanceToTop < animationStartHeight) + newHeight = Math.min(topInset * (animationStartHeight - distanceToTop) / 100, topInset); + if (newHeight > 0) + { + mPlacePageStatusBarBackground.setTranslationY(distanceToTop - newHeight); + if (!UiUtils.isVisible(mPlacePageStatusBarBackground)) + UiUtils.show(mPlacePageStatusBarBackground); + } + else if (UiUtils.isVisible(mPlacePageStatusBarBackground)) + UiUtils.hide(mPlacePageStatusBarBackground); + } + } + @Override public void onStart() { super.onStart(); mPlacePageBehavior.addBottomSheetCallback(mDefaultBottomSheetCallback); mViewModel.getMapObject().observe(requireActivity(), this); + mViewModel.getPlacePageDistanceToTop().observe(requireActivity(), mPlacePageDistanceToTopObserver); } @Override @@ -590,6 +637,7 @@ public class PlacePageController extends Fragment implements super.onStop(); mPlacePageBehavior.removeBottomSheetCallback(mDefaultBottomSheetCallback); mViewModel.getMapObject().removeObserver(this); + mViewModel.getPlacePageDistanceToTop().removeObserver(mPlacePageDistanceToTopObserver); } public interface PlacePageRouteSettingsListener