diff --git a/android/res/layout/activity_map.xml b/android/res/layout/activity_map.xml
index 9e74ce13d2..abe4998ff8 100644
--- a/android/res/layout/activity_map.xml
+++ b/android/res/layout/activity_map.xml
@@ -1,7 +1,6 @@
-
-
-
-
-
+ android:layout_height="match_parent"
+ android:name="app.organicmaps.widget.placepage.PlacePageController" />
diff --git a/android/res/layout/place_page_container_fragment.xml b/android/res/layout/place_page_container_fragment.xml
new file mode 100644
index 0000000000..f53af67f3a
--- /dev/null
+++ b/android/res/layout/place_page_container_fragment.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/src/app/organicmaps/MwmActivity.java b/android/src/app/organicmaps/MwmActivity.java
index 3e0a973f44..106a35c8e2 100644
--- a/android/src/app/organicmaps/MwmActivity.java
+++ b/android/src/app/organicmaps/MwmActivity.java
@@ -26,6 +26,7 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
+import androidx.lifecycle.ViewModelProvider;
import app.organicmaps.Framework.PlacePageActivationListener;
import app.organicmaps.api.Const;
import app.organicmaps.background.Notifier;
@@ -88,18 +89,15 @@ import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import app.organicmaps.util.log.Logger;
import app.organicmaps.widget.menu.MainMenu;
-import app.organicmaps.widget.placepage.PlacePageButtons;
import app.organicmaps.widget.placepage.PlacePageController;
import app.organicmaps.widget.placepage.PlacePageData;
-import app.organicmaps.widget.placepage.PlacePageView;
+import app.organicmaps.widget.placepage.PlacePageViewModel;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Stack;
-import static app.organicmaps.widget.placepage.PlacePageButtons.PLACEPAGE_MORE_MENU_ID;
-
public class MwmActivity extends BaseMwmFragmentActivity
implements PlacePageActivationListener,
View.OnTouchListener,
@@ -112,12 +110,11 @@ public class MwmActivity extends BaseMwmFragmentActivity
RoutingBottomMenuListener,
BookmarkManager.BookmarksLoadingListener,
FloatingSearchToolbarController.SearchToolbarListener,
- PlacePageController.SlideListener,
NoConnectionListener,
MenuBottomSheetFragment.MenuBottomSheetInterfaceWithHeader,
+ PlacePageController.PlacePageRouteSettingsListener,
+ MapButtonsController.MapButtonClickListener,
ToggleMapLayerFragment.LayerItemClickListener,
- PlacePageButtons.PlacePageButtonClickListener,
- PlacePageView.PlacePageViewListener
{
private static final String TAG = MwmActivity.class.getSimpleName();
@@ -184,15 +181,14 @@ public class MwmActivity extends BaseMwmFragmentActivity
private boolean mRestoreRoutingPlanFragmentNeeded;
@Nullable
private Bundle mSavedForTabletState;
- @SuppressWarnings("NotNullFieldNotInitialized")
- @NonNull
- private PlacePageController mPlacePageController;
private MapButtonsController.LayoutMode mCurrentLayoutMode;
private String mDonatesUrl;
private int mNavBarHeight;
+ private PlacePageViewModel mPlacePageViewModel;
+
@Nullable
private WindowInsetsCompat mCurrentWindowInsets;
@@ -380,8 +376,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
setContentView(R.layout.activity_map);
UiUtils.setupTransparentStatusBar(this);
- mPlacePageController = new PlacePageController(this, this);
- mPlacePageController.initialize(this);
+ mPlacePageViewModel = new ViewModelProvider(this).get(PlacePageViewModel.class);
mSearchController = new FloatingSearchToolbarController(this, this);
mSearchController.getToolbar()
@@ -616,7 +611,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
LocationState.nativeGetMode(),
this::onMapButtonClick,
(v) -> closeSearchToolbar(true, true),
- mPlacePageController,
this::updateBottomWidgetsOffset);
@@ -687,10 +681,10 @@ public class MwmActivity extends BaseMwmFragmentActivity
*/
public boolean closePlacePage()
{
- if (mPlacePageController.isClosed())
+ if (mPlacePageViewModel.getMapObject().getValue() == null)
return false;
- mPlacePageController.close(true);
+ mPlacePageViewModel.setMapObject(null);
return true;
}
@@ -817,7 +811,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
@Override
protected void onSaveInstanceState(@NonNull Bundle outState)
{
- mPlacePageController.onSave(outState);
if (!mIsTabletLayout && RoutingController.get().isPlanning())
mRoutingPlanInplaceController.onSaveState(outState);
@@ -848,7 +841,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
- mPlacePageController.onRestore(savedInstanceState);
if (mIsTabletLayout)
{
RoutingPlanFragment fragment = (RoutingPlanFragment) getFragment(RoutingPlanFragment.class);
@@ -1054,8 +1046,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
super.onSafeDestroy();
mNavigationController.destroy();
- //TrafficManager.INSTANCE.detachAll();
- mPlacePageController.destroy();
}
@Override
@@ -1134,8 +1124,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onPlacePageActivated(@NonNull PlacePageData data)
{
setFullscreen(false);
-
- mPlacePageController.openFor(data);
+ // This will open the place page
+ mPlacePageViewModel.setMapObject((MapObject) data);
}
// Called from JNI.
@@ -1168,12 +1158,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
UiUtils.setFullscreen(this, isFullscreen);
}
- @Override
- public void onPlacePageSlide(int top)
- {
- mMapButtonsController.move(top);
- }
-
@Override
public boolean onTouch(View view, MotionEvent event)
{
@@ -1835,8 +1819,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
items.add(new MenuBottomSheetItem(R.string.share_my_location, R.drawable.ic_share, this::onShareLocationOptionSelected));
return items;
}
- else if (id.equals(PLACEPAGE_MORE_MENU_ID))
- return mPlacePageController.getMenuBottomSheetItems(id);
return null;
}
@@ -1849,30 +1831,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
return null;
}
- @Override
- public void onPlacePageButtonClick(PlacePageButtons.ButtonType item)
- {
- mPlacePageController.onPlacePageButtonClick(item);
- }
-
- @Override
- public void onPlacePageContentChanged(int previewHeight, int frameHeight)
- {
- mPlacePageController.onPlacePageContentChanged(previewHeight, frameHeight);
- }
-
- @Override
- public void onPlacePageRequestClose()
- {
- mPlacePageController.onPlacePageRequestClose();
- }
-
- @Override
- public void onPlacePageRequestToggleState()
- {
- mPlacePageController.onPlacePageRequestToggleState();
- }
-
@Override
public void onPlacePageRequestToggleRouteSettings(@NonNull RoadType roadType)
{
diff --git a/android/src/app/organicmaps/maplayer/MapButtonsController.java b/android/src/app/organicmaps/maplayer/MapButtonsController.java
index ca948cf4c5..de7dfb813f 100644
--- a/android/src/app/organicmaps/maplayer/MapButtonsController.java
+++ b/android/src/app/organicmaps/maplayer/MapButtonsController.java
@@ -13,6 +13,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
import app.organicmaps.R;
import app.organicmaps.downloader.MapManager;
import app.organicmaps.downloader.UpdateInfo;
@@ -21,7 +22,7 @@ import app.organicmaps.util.Config;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.widget.menu.MyPositionButton;
-import app.organicmaps.widget.placepage.PlacePageController;
+import app.organicmaps.widget.placepage.PlacePageViewModel;
import com.google.android.material.badge.BadgeDrawable;
import com.google.android.material.badge.BadgeUtils;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
@@ -49,11 +50,11 @@ public class MapButtonsController extends Fragment
private MapButtonClickListener mMapButtonClickListener;
private View.OnClickListener mOnSearchCanceledListener;
- private PlacePageController mPlacePageController;
private OnBottomButtonsHeightChangedListener mOnBottomButtonsHeightChangedListener;
private LayoutMode mLayoutMode;
private int mMyPositionMode;
+ private PlacePageViewModel mViewModel;
@Nullable
@Override
@@ -136,6 +137,8 @@ public class MapButtonsController extends Fragment
return windowInsets;
});
+ mViewModel = new ViewModelProvider(requireActivity()).get(PlacePageViewModel.class);
+
return mFrame;
}
@@ -144,13 +147,12 @@ public class MapButtonsController extends Fragment
return mLayoutMode;
}
- public void init(LayoutMode layoutMode, int myPositionMode, MapButtonClickListener mapButtonClickListener, @NonNull View.OnClickListener onSearchCanceledListener, PlacePageController placePageController, OnBottomButtonsHeightChangedListener onBottomButtonsHeightChangedListener)
+ public void init(LayoutMode layoutMode, int myPositionMode, MapButtonClickListener mapButtonClickListener, @NonNull View.OnClickListener onSearchCanceledListener, OnBottomButtonsHeightChangedListener onBottomButtonsHeightChangedListener)
{
mLayoutMode = layoutMode;
mMyPositionMode = myPositionMode;
mMapButtonClickListener = mapButtonClickListener;
mOnSearchCanceledListener = onSearchCanceledListener;
- mPlacePageController = placePageController;
mOnBottomButtonsHeightChangedListener = onBottomButtonsHeightChangedListener;
}
@@ -209,7 +211,10 @@ public class MapButtonsController extends Fragment
private boolean isBehindPlacePage(View v)
{
- return !(mContentWidth / 2 > (mPlacePageController.getPlacePageWidth() / 2.0) + v.getWidth());
+ if (mViewModel == null)
+ return false;
+ final int placePageWidth = mViewModel.getPlacePageWidth().getValue();
+ return !(mContentWidth / 2 > (placePageWidth / 2.0) + v.getWidth());
}
private boolean isMoving(View v)
@@ -301,9 +306,16 @@ public class MapButtonsController extends Fragment
return (int) (translation + v.getTop());
}
+ @Override
+ public void onPause()
+ {
+ super.onPause();
+ mViewModel.getPlacePageDistanceToTop().removeObserver(this::move);
+ }
public void onResume()
{
super.onResume();
+ mViewModel.getPlacePageDistanceToTop().observe(requireActivity(), this::move);
mSearchWheel.onResume();
updateMenuBadge();
}
diff --git a/android/src/app/organicmaps/widget/placepage/PlacePageButtons.java b/android/src/app/organicmaps/widget/placepage/PlacePageButtons.java
index abecaa59b9..6cd35663bb 100644
--- a/android/src/app/organicmaps/widget/placepage/PlacePageButtons.java
+++ b/android/src/app/organicmaps/widget/placepage/PlacePageButtons.java
@@ -1,6 +1,5 @@
package app.organicmaps.widget.placepage;
-import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -50,28 +49,24 @@ public final class PlacePageButtons extends Fragment implements Observer buttons)
diff --git a/android/src/app/organicmaps/widget/placepage/PlacePageController.java b/android/src/app/organicmaps/widget/placepage/PlacePageController.java
index 590929cb26..e3b15a7eb7 100644
--- a/android/src/app/organicmaps/widget/placepage/PlacePageController.java
+++ b/android/src/app/organicmaps/widget/placepage/PlacePageController.java
@@ -1,96 +1,82 @@
package app.organicmaps.widget.placepage;
import android.animation.ValueAnimator;
-import android.annotation.SuppressLint;
import android.app.Activity;
+import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.widget.NestedScrollViewClickFixed;
import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
-import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import app.organicmaps.Framework;
import app.organicmaps.MwmActivity;
import app.organicmaps.R;
+import app.organicmaps.api.Const;
import app.organicmaps.api.ParsedMwmRequest;
-import app.organicmaps.base.Initializable;
-import app.organicmaps.base.Savable;
+import app.organicmaps.bookmarks.data.BookmarkManager;
import app.organicmaps.bookmarks.data.MapObject;
import app.organicmaps.bookmarks.data.RoadWarningMarkType;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.settings.RoadType;
+import app.organicmaps.util.SharingUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import app.organicmaps.util.log.Logger;
-
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
-public class PlacePageController implements Initializable,
- Savable,
- PlacePageView.PlacePageViewListener,
- PlacePageButtons.PlacePageButtonClickListener,
- MenuBottomSheetFragment.MenuBottomSheetInterface,
- Observer
+public class PlacePageController extends Fragment implements
+ PlacePageView.PlacePageViewListener,
+ PlacePageButtons.PlacePageButtonClickListener,
+ MenuBottomSheetFragment.MenuBottomSheetInterface,
+ Observer
{
private static final String TAG = PlacePageController.class.getSimpleName();
private static final String PLACE_PAGE_BUTTONS_FRAGMENT_TAG = "PLACE_PAGE_BUTTONS";
private static final String PLACE_PAGE_FRAGMENT_TAG = "PLACE_PAGE";
private static final float PREVIEW_PLUS_RATIO = 0.45f;
- @NonNull
- private final SlideListener mSlideListener;
- @NonNull
- private final BottomSheetBehavior mPlacePageBehavior;
- @NonNull
- private final NestedScrollViewClickFixed mPlacePage;
- @NonNull
- private final ViewGroup mPlacePageContainer;
- private final ViewGroup mCoordinator;
- private final int mViewportMinHeight;
- private final AppCompatActivity mMwmActivity;
- private final int mButtonsHeight;
- private final int mMaxButtons;
- private final PlacePageViewModel mViewModel;
+ private BottomSheetBehavior mPlacePageBehavior;
+ private NestedScrollViewClickFixed mPlacePage;
+ private ViewGroup mPlacePageContainer;
+ private ViewGroup mCoordinator;
+ private int mViewportMinHeight;
+ private int mButtonsHeight;
+ private int mMaxButtons;
+ private PlacePageViewModel mViewModel;
private int mPreviewHeight;
private int mFrameHeight;
- private boolean mDeactivateMapSelection = true;
@Nullable
private MapObject mMapObject;
+ @Nullable
+ private MapObject mPreviousMapObject;
private WindowInsetsCompat mCurrentWindowInsets;
private boolean mShouldCollapse;
private int mDistanceToTop;
private ValueAnimator mCustomPeekHeightAnimator;
-
- class DefaultBottomSheetCallback extends BottomSheetBehavior.BottomSheetCallback
+ private PlacePageRouteSettingsListener mPlacePageRouteSettingsListener;
+ private final BottomSheetBehavior.BottomSheetCallback mDefaultBottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback()
{
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState)
{
- final Lifecycle.State state = mMwmActivity.getLifecycle().getCurrentState();
- if (!state.isAtLeast(Lifecycle.State.RESUMED))
- {
- Logger.e(TAG, "Called in the wrong activity state=" + state);
- return;
- }
-
Logger.d(TAG, "State change, new = " + PlacePageUtils.toString(newState));
if (PlacePageUtils.isSettlingState(newState) || PlacePageUtils.isDraggingState(newState))
return;
@@ -104,51 +90,48 @@ public class PlacePageController implements Initializable,
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset)
{
- final Lifecycle.State state = mMwmActivity.getLifecycle().getCurrentState();
- if (!state.isAtLeast(Lifecycle.State.RESUMED))
- {
- Logger.e(TAG, "Called in the wrong activity state=" + state);
- return;
- }
stopCustomPeekHeightAnimation();
mDistanceToTop = bottomSheet.getTop();
- mSlideListener.onPlacePageSlide(mDistanceToTop);
+ mViewModel.setPlacePageDistanceToTop(mDistanceToTop);
}
+ };
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
+ {
+ return inflater.inflate(R.layout.place_page_container_fragment, container, false);
}
- @SuppressLint("ClickableViewAccessibility")
- public PlacePageController(@Nullable Activity activity,
- @NonNull SlideListener listener)
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
{
- mSlideListener = listener;
+ super.onViewCreated(view, savedInstanceState);
+ final FragmentActivity activity = requireActivity();
+ mPlacePageRouteSettingsListener = (MwmActivity) activity;
- Objects.requireNonNull(activity);
- mMwmActivity = (AppCompatActivity) activity;
- mCoordinator = mMwmActivity.findViewById(R.id.coordinator);
- Resources res = activity.getResources();
+ final Resources res = activity.getResources();
mViewportMinHeight = res.getDimensionPixelSize(R.dimen.viewport_min_height);
- mPlacePage = activity.findViewById(R.id.placepage);
- mPlacePageContainer = activity.findViewById(R.id.placepage_container);
+ mButtonsHeight = (int) res.getDimension(R.dimen.place_page_buttons_height);
+ mMaxButtons = res.getInteger(R.integer.pp_buttons_max);
+
+ mCoordinator = activity.findViewById(R.id.coordinator);
+ mPlacePage = view.findViewById(R.id.placepage);
+ mPlacePageContainer = view.findViewById(R.id.placepage_container);
mPlacePageBehavior = BottomSheetBehavior.from(mPlacePage);
mShouldCollapse = true;
- mPlacePageBehavior.addBottomSheetCallback(new DefaultBottomSheetCallback());
mPlacePageBehavior.setHideable(true);
mPlacePageBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
mPlacePageBehavior.setFitToContents(true);
mPlacePageBehavior.setSkipCollapsed(true);
- UiUtils.bringViewToFrontOf(activity.findViewById(R.id.pp_buttons_fragment), mPlacePage);
+ UiUtils.bringViewToFrontOf(view.findViewById(R.id.pp_buttons_fragment), mPlacePage);
- mPlacePage.requestApplyInsets();
+ mViewModel = new ViewModelProvider(requireActivity()).get(PlacePageViewModel.class);
- mButtonsHeight = (int) mMwmActivity.getResources()
- .getDimension(R.dimen.place_page_buttons_height);
- mMaxButtons = mMwmActivity.getResources().getInteger(R.integer.pp_buttons_max);
- mViewModel = new ViewModelProvider(mMwmActivity).get(PlacePageViewModel.class);
-
- ViewCompat.setOnApplyWindowInsetsListener(mPlacePage, (view, windowInsets) -> {
+ ViewCompat.setOnApplyWindowInsetsListener(mPlacePage, (v, windowInsets) -> {
mCurrentWindowInsets = windowInsets;
return windowInsets;
});
@@ -181,19 +164,12 @@ public class PlacePageController implements Initializable,
private void onHiddenInternal()
{
- if (mDeactivateMapSelection)
- Framework.nativeDeactivatePopup();
- mDeactivateMapSelection = true;
+ Framework.nativeDeactivatePopup();
PlacePageUtils.moveViewportUp(mPlacePage, mViewportMinHeight);
resetPlacePageHeightBounds();
removePlacePageFragments();
}
- public int getPlacePageWidth()
- {
- return mPlacePage.getWidth();
- }
-
@Nullable
public ArrayList getMenuBottomSheetItems(String id)
{
@@ -203,24 +179,27 @@ public class PlacePageController implements Initializable,
ArrayList items = new ArrayList<>();
for (int i = mMaxButtons - 1; i < currentItems.size(); i++)
{
- final PlacePageButton bsItem = PlacePageButtonFactory.createButton(currentItems.get(i), mMwmActivity);
+ final PlacePageButton bsItem = PlacePageButtonFactory.createButton(currentItems.get(i), requireActivity());
items.add(new MenuBottomSheetItem(
bsItem.getTitle(),
bsItem.getIcon(),
- () -> ((PlacePageButtons.PlacePageButtonClickListener) mMwmActivity).onPlacePageButtonClick(bsItem.getType())
+ () -> onPlacePageButtonClick(bsItem.getType())
));
}
return items;
}
- public void openFor(@NonNull PlacePageData data)
+ private void open()
{
- mDeactivateMapSelection = true;
- MapObject mapObject = (MapObject) data;
- final MapObject previousMapObject = mViewModel.getMapObject().getValue();
// Only collapse the place page if the data is different from the one already available
- mShouldCollapse = PlacePageUtils.isHiddenState(mPlacePageBehavior.getState()) || !MapObject.same(previousMapObject, mapObject);
- mViewModel.setMapObject(mapObject);
+ mShouldCollapse = PlacePageUtils.isHiddenState(mPlacePageBehavior.getState()) || !MapObject.same(mPreviousMapObject, mMapObject);
+ mPreviousMapObject = mMapObject;
+ // Place page will automatically open when the bottom sheet content is loaded so we can compute the peek height
+ }
+
+ private void close()
+ {
+ mPlacePageBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
private void resetPlacePageHeightBounds()
@@ -299,7 +278,7 @@ public class PlacePageController implements Initializable,
mPlacePageBehavior.setPeekHeight(value);
// The place page is not firing the slide callbacks when using this animation, so we must call them manually
mDistanceToTop = parentHeight - value - bottomInsets;
- mSlideListener.onPlacePageSlide(mDistanceToTop);
+ mViewModel.setPlacePageDistanceToTop(mDistanceToTop);
if (value == peekHeight)
{
PlacePageUtils.moveViewportUp(mPlacePage, mViewportMinHeight);
@@ -317,37 +296,12 @@ public class PlacePageController implements Initializable,
return mPreviewHeight + mButtonsHeight;
}
- public void close(boolean deactivateMapSelection)
- {
- mDeactivateMapSelection = deactivateMapSelection;
- mPlacePageBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
- }
-
- public boolean isClosed()
- {
- return PlacePageUtils.isHiddenState(mPlacePageBehavior.getState());
- }
-
- @Override
- public void onSave(@NonNull Bundle outState)
- {
- // no op
- }
-
- @Override
- public void onRestore(@NonNull Bundle inState)
- {
- if (mPlacePageBehavior.getState() == BottomSheetBehavior.STATE_HIDDEN)
- return;
- if (!Framework.nativeHasPlacePageInfo())
- close(false);
- }
-
@Override
public void onPlacePageContentChanged(int previewHeight, int frameHeight)
{
mPreviewHeight = previewHeight;
mFrameHeight = frameHeight;
+ mViewModel.setPlacePageWidth(mPlacePage.getWidth());
// Make sure to update the peek height on the UI thread to prevent weird animation jumps
mPlacePage.post(() -> {
setPeekHeight();
@@ -357,12 +311,6 @@ public class PlacePageController implements Initializable,
});
}
- @Override
- public void onPlacePageRequestClose()
- {
- close(true);
- }
-
@Override
public void onPlacePageRequestToggleState()
{
@@ -375,24 +323,150 @@ public class PlacePageController implements Initializable,
mPlacePageBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
- @Override
- public void onPlacePageRequestToggleRouteSettings(@NonNull RoadType roadType)
- {
- // no op
- }
-
@Override
public void onPlacePageButtonClick(PlacePageButtons.ButtonType item)
{
- @Nullable final PlacePageView placePageFragment = (PlacePageView) mMwmActivity.getSupportFragmentManager()
- .findFragmentByTag(PLACE_PAGE_FRAGMENT_TAG);
- if (placePageFragment != null)
- placePageFragment.onPlacePageButtonClick(item);
+ switch (item)
+ {
+ case BOOKMARK_SAVE:
+ case BOOKMARK_DELETE:
+ onBookmarkBtnClicked();
+ break;
+
+ case SHARE:
+ onShareBtnClicked();
+ break;
+
+ case BACK:
+ onBackBtnClicked();
+ break;
+
+ case ROUTE_FROM:
+ onRouteFromBtnClicked();
+ break;
+
+ case ROUTE_TO:
+ onRouteToBtnClicked();
+ break;
+
+ case ROUTE_ADD:
+ onRouteAddBtnClicked();
+ break;
+
+ case ROUTE_REMOVE:
+ onRouteRemoveBtnClicked();
+ break;
+
+ case ROUTE_AVOID_TOLL:
+ onAvoidTollBtnClicked();
+ break;
+
+ case ROUTE_AVOID_UNPAVED:
+ onAvoidUnpavedBtnClicked();
+ break;
+
+ case ROUTE_AVOID_FERRY:
+ onAvoidFerryBtnClicked();
+ break;
+ }
+ }
+
+ private void onBookmarkBtnClicked()
+ {
+ // No need to call setMapObject here as the native methods will reopen the place page
+ if (MapObject.isOfType(MapObject.BOOKMARK, mMapObject))
+ Framework.nativeDeleteBookmarkFromMapObject();
+ else
+ BookmarkManager.INSTANCE.addNewBookmark(mMapObject.getLat(), mMapObject.getLon());
+ }
+
+ private void onShareBtnClicked()
+ {
+ if (mMapObject != null)
+ SharingUtils.shareMapObject(requireContext(), mMapObject);
+ }
+
+ private void onBackBtnClicked()
+ {
+ if (mMapObject == null)
+ return;
+ final ParsedMwmRequest request = ParsedMwmRequest.getCurrentRequest();
+ if (request != null && request.isPickPointMode())
+ {
+ final Intent result = new Intent();
+ result.putExtra(Const.EXTRA_POINT_LAT, mMapObject.getLat())
+ .putExtra(Const.EXTRA_POINT_LON, mMapObject.getLon())
+ .putExtra(Const.EXTRA_POINT_NAME, mMapObject.getTitle())
+ .putExtra(Const.EXTRA_POINT_ID, mMapObject.getApiId())
+ .putExtra(Const.EXTRA_ZOOM_LEVEL, Framework.nativeGetDrawScale());
+ requireActivity().setResult(Activity.RESULT_OK, result);
+ ParsedMwmRequest.setCurrentRequest(null);
+ }
+ requireActivity().finish();
+ }
+
+ private void onRouteFromBtnClicked()
+ {
+ if (mMapObject == null)
+ return;
+ RoutingController controller = RoutingController.get();
+ if (!controller.isPlanning())
+ {
+ controller.prepare(mMapObject, null);
+ close();
+ }
+ else if (controller.setStartPoint(mMapObject))
+ close();
+ }
+
+ private void onRouteToBtnClicked()
+ {
+ if (mMapObject == null)
+ return;
+ if (RoutingController.get().isPlanning())
+ {
+ RoutingController.get().setEndPoint(mMapObject);
+ close();
+ }
+ else
+ ((MwmActivity) requireActivity()).startLocationToPoint(mMapObject);
+ }
+
+ private void onRouteAddBtnClicked()
+ {
+ if (mMapObject != null)
+ RoutingController.get().addStop(mMapObject);
+ }
+
+ private void onRouteRemoveBtnClicked()
+ {
+ if (mMapObject != null)
+ RoutingController.get().removeStop(mMapObject);
+ }
+
+ private void onAvoidUnpavedBtnClicked()
+ {
+ onAvoidBtnClicked(RoadType.Dirty);
+ }
+
+ private void onAvoidFerryBtnClicked()
+ {
+ onAvoidBtnClicked(RoadType.Ferry);
+ }
+
+ private void onAvoidTollBtnClicked()
+ {
+ onAvoidBtnClicked(RoadType.Toll);
+ }
+
+ private void onAvoidBtnClicked(@NonNull RoadType roadType)
+ {
+ mPlacePageRouteSettingsListener.onPlacePageRequestToggleRouteSettings(roadType);
}
private void removePlacePageFragments()
{
- final FragmentManager fm = mMwmActivity.getSupportFragmentManager();
+ final FragmentManager fm = getChildFragmentManager();
final Fragment placePageButtonsFragment = fm.findFragmentByTag(PLACE_PAGE_BUTTONS_FRAGMENT_TAG);
final Fragment placePageFragment = fm.findFragmentByTag(PLACE_PAGE_FRAGMENT_TAG);
@@ -401,23 +475,21 @@ public class PlacePageController implements Initializable,
fm.beginTransaction()
.setReorderingAllowed(true)
.remove(placePageButtonsFragment)
- .commitNow();
+ .commit();
}
if (placePageFragment != null)
{
- // Make sure to synchronously remove the fragment so setting the map object to null
- // won't impact the fragment
fm.beginTransaction()
.setReorderingAllowed(true)
.remove(placePageFragment)
- .commitNow();
+ .commit();
}
mViewModel.setMapObject(null);
}
private void createPlacePageFragments()
{
- final FragmentManager fm = mMwmActivity.getSupportFragmentManager();
+ final FragmentManager fm = getChildFragmentManager();
if (fm.findFragmentByTag(PLACE_PAGE_FRAGMENT_TAG) == null)
{
fm.beginTransaction()
@@ -486,29 +558,42 @@ public class PlacePageController implements Initializable,
mMapObject = mapObject;
if (mapObject != null)
{
+ open();
createPlacePageFragments();
updateButtons(
mapObject,
MapObject.isOfType(MapObject.API_POINT, mMapObject),
!MapObject.isOfType(MapObject.MY_POSITION, mMapObject));
- }
+ } else
+ close();
}
@Override
- public void initialize(@Nullable Activity activity)
+ public void onStart()
{
- Objects.requireNonNull(activity);
- mViewModel.getMapObject().observe((MwmActivity) activity, this);
+ super.onStart();
+ mPlacePageBehavior.addBottomSheetCallback(mDefaultBottomSheetCallback);
+ mViewModel.getMapObject().observe(requireActivity(), this);
}
@Override
- public void destroy()
+ public void onResume()
{
+ super.onResume();
+ if (mPlacePageBehavior.getState() != BottomSheetBehavior.STATE_HIDDEN && !Framework.nativeHasPlacePageInfo())
+ mViewModel.setMapObject(null);
+ }
+
+ @Override
+ public void onStop()
+ {
+ super.onStop();
+ mPlacePageBehavior.removeBottomSheetCallback(mDefaultBottomSheetCallback);
mViewModel.getMapObject().removeObserver(this);
}
- public interface SlideListener
+ public interface PlacePageRouteSettingsListener
{
- void onPlacePageSlide(int top);
+ void onPlacePageRequestToggleRouteSettings(@NonNull RoadType roadType);
}
}
diff --git a/android/src/app/organicmaps/widget/placepage/PlacePageView.java b/android/src/app/organicmaps/widget/placepage/PlacePageView.java
index 2392c98c93..21ee2ebb45 100644
--- a/android/src/app/organicmaps/widget/placepage/PlacePageView.java
+++ b/android/src/app/organicmaps/widget/placepage/PlacePageView.java
@@ -1,8 +1,6 @@
package app.organicmaps.widget.placepage;
-import android.app.Activity;
import android.content.Context;
-import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
@@ -29,9 +27,6 @@ import app.organicmaps.Framework;
import app.organicmaps.MwmActivity;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
-import app.organicmaps.api.Const;
-import app.organicmaps.api.ParsedMwmRequest;
-import app.organicmaps.bookmarks.data.BookmarkManager;
import app.organicmaps.bookmarks.data.DistanceAndAzimut;
import app.organicmaps.bookmarks.data.MapObject;
import app.organicmaps.bookmarks.data.Metadata;
@@ -42,8 +37,6 @@ import app.organicmaps.editor.Editor;
import app.organicmaps.location.LocationHelper;
import app.organicmaps.location.LocationListener;
import app.organicmaps.routing.RoutingController;
-import app.organicmaps.settings.RoadType;
-import app.organicmaps.util.SharingUtils;
import app.organicmaps.util.StringUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.concurrency.UiThread;
@@ -63,7 +56,6 @@ import static android.view.View.VISIBLE;
public class PlacePageView extends Fragment implements View.OnClickListener,
View.OnLongClickListener,
- PlacePageButtons.PlacePageButtonClickListener,
LocationListener,
Observer
@@ -181,6 +173,9 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
MwmApplication.prefs(requireContext()).getInt(
PREF_COORDINATES_FORMAT, CoordinatesFormat.LatLonDecimal.getId()));
+ Fragment parentFragment = getParentFragment();
+ mPlacePageViewListener = (PlacePageViewListener) parentFragment;
+
mFrame = view;
mFrame.setOnClickListener((v) -> mPlacePageViewListener.onPlacePageRequestToggleState());
@@ -243,186 +238,30 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
mDownloaderIcon = new DownloaderStatusIcon(mPreview.findViewById(R.id.downloader_status_frame));
mDownloaderInfo = mPreview.findViewById(R.id.tv__downloader_details);
-
- mMapObject = mViewModel.getMapObject().getValue();
}
@Override
- public void onAttach(@NonNull Context context)
+ public void onStart()
{
- super.onAttach(context);
- mPlacePageViewListener = (MwmActivity) context;
- }
-
- @Override
- public void onResume()
- {
- super.onResume();
+ super.onStart();
mViewModel.getMapObject().observe(requireActivity(), this);
LocationHelper.INSTANCE.addListener(this);
- }
-
- @Override
- public void onPause()
- {
- super.onPause();
- // Unsubscribe from events as soon as the fragment becomes inactive
- // to prevent unwanted side effects
- mViewModel.getMapObject().removeObserver(this);
- LocationHelper.INSTANCE.removeListener(this);
+ setCurrentCountry();
}
@Override
public void onStop()
{
super.onStop();
- // Safely detach the country once the fragment is hidden from the user
- // It is safer to call this here than in onPause as the app could go from onPause to
- // onResume without killing the fragment.
- // In this case we would not want to detach the country.
+ mViewModel.getMapObject().removeObserver(this);
+ LocationHelper.INSTANCE.removeListener(this);
detachCountry();
}
- @Override
- public void onPlacePageButtonClick(PlacePageButtons.ButtonType item)
- {
- switch (item)
- {
- case BOOKMARK_SAVE:
- case BOOKMARK_DELETE:
- onBookmarkBtnClicked();
- break;
-
- case SHARE:
- onShareBtnClicked();
- break;
-
- case BACK:
- onBackBtnClicked();
- break;
-
- case ROUTE_FROM:
- onRouteFromBtnClicked();
- break;
-
- case ROUTE_TO:
- onRouteToBtnClicked();
- break;
-
- case ROUTE_ADD:
- onRouteAddBtnClicked();
- break;
-
- case ROUTE_REMOVE:
- onRouteRemoveBtnClicked();
- break;
-
- case ROUTE_AVOID_TOLL:
- onAvoidTollBtnClicked();
- break;
-
- case ROUTE_AVOID_UNPAVED:
- onAvoidUnpavedBtnClicked();
- break;
-
- case ROUTE_AVOID_FERRY:
- onAvoidFerryBtnClicked();
- break;
- }
- }
-
- private void onBookmarkBtnClicked()
- {
- // No need to call setMapObject here as the native methods will reopen the place page
- if (MapObject.isOfType(MapObject.BOOKMARK, mMapObject))
- Framework.nativeDeleteBookmarkFromMapObject();
- else
- BookmarkManager.INSTANCE.addNewBookmark(mMapObject.getLat(), mMapObject.getLon());
- }
-
- private void onShareBtnClicked()
- {
- SharingUtils.shareMapObject(requireContext(), mMapObject);
- }
-
- private void onBackBtnClicked()
- {
- final ParsedMwmRequest request = ParsedMwmRequest.getCurrentRequest();
- if (request != null && request.isPickPointMode())
- {
- final Intent result = new Intent();
- result.putExtra(Const.EXTRA_POINT_LAT, mMapObject.getLat())
- .putExtra(Const.EXTRA_POINT_LON, mMapObject.getLon())
- .putExtra(Const.EXTRA_POINT_NAME, mMapObject.getTitle())
- .putExtra(Const.EXTRA_POINT_ID, mMapObject.getApiId())
- .putExtra(Const.EXTRA_ZOOM_LEVEL, Framework.nativeGetDrawScale());
- requireActivity().setResult(Activity.RESULT_OK, result);
- ParsedMwmRequest.setCurrentRequest(null);
- }
- requireActivity().finish();
- }
-
- private void onRouteFromBtnClicked()
- {
- RoutingController controller = RoutingController.get();
- if (!controller.isPlanning())
- {
- controller.prepare(mMapObject, null);
- mPlacePageViewListener.onPlacePageRequestClose();
- }
- else if (controller.setStartPoint(mMapObject))
- {
- mPlacePageViewListener.onPlacePageRequestClose();
- }
- }
-
- private void onRouteToBtnClicked()
- {
- if (RoutingController.get().isPlanning())
- {
- RoutingController.get().setEndPoint(mMapObject);
- mPlacePageViewListener.onPlacePageRequestClose();
- }
- else
- {
- ((MwmActivity) requireActivity()).startLocationToPoint(mMapObject);
- }
- }
-
- private void onRouteAddBtnClicked()
- {
- RoutingController.get().addStop(mMapObject);
- }
-
- private void onRouteRemoveBtnClicked()
- {
- RoutingController.get().removeStop(mMapObject);
- }
-
- private void onAvoidUnpavedBtnClicked()
- {
- onAvoidBtnClicked(RoadType.Dirty);
- }
-
- private void onAvoidFerryBtnClicked()
- {
- onAvoidBtnClicked(RoadType.Ferry);
- }
-
- private void onAvoidTollBtnClicked()
- {
- onAvoidBtnClicked(RoadType.Toll);
- }
-
- private void onAvoidBtnClicked(@NonNull RoadType roadType)
- {
- mPlacePageViewListener.onPlacePageRequestToggleRouteSettings(roadType);
- }
-
private void setCurrentCountry()
{
- if (mCurrentCountry != null)
- throw new AssertionError("country should be detached before!");
+ if (mCurrentCountry != null || mMapObject == null)
+ return;
String country = MapManager.nativeGetSelectedCountry();
if (country != null && !RoutingController.get().isNavigating())
attachCountry(country);
@@ -455,7 +294,7 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
fm.beginTransaction()
.setReorderingAllowed(true)
.remove(fragment)
- .commitNow();
+ .commit();
}
}
@@ -504,7 +343,7 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
int end = text.lastIndexOf("★") + 1;
if (start > -1)
{
- sb.setSpan(new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.base_yellow)),
+ sb.setSpan(new ForegroundColorSpan(ContextCompat.getColor(requireContext(), R.color.base_yellow)),
start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
mTvSubtitle.setText(sb);
@@ -758,8 +597,10 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
}
@Override
- public void onChanged(MapObject mapObject)
+ public void onChanged(@Nullable MapObject mapObject)
{
+ if (mapObject == null)
+ return;
if (!mapObject.sameAs(mMapObject))
{
detachCountry();
@@ -778,6 +619,8 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
@Override
public void onLocationUpdated(@NonNull Location location)
{
+ if (mMapObject == null)
+ return;
if (MapObject.isOfType(MapObject.MY_POSITION, mMapObject))
refreshMyPosition(location);
else
@@ -787,7 +630,7 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
@Override
public void onCompassUpdated(double north)
{
- if (MapObject.isOfType(MapObject.MY_POSITION, mMapObject))
+ if (mMapObject == null || MapObject.isOfType(MapObject.MY_POSITION, mMapObject))
return;
final Location location = LocationHelper.INSTANCE.getSavedLocation();
@@ -815,10 +658,6 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
// Called when the content has actually changed and we are ready to compute the peek height
void onPlacePageContentChanged(int previewHeight, int frameHeight);
- void onPlacePageRequestClose();
-
void onPlacePageRequestToggleState();
-
- void onPlacePageRequestToggleRouteSettings(@NonNull RoadType roadType);
}
}
diff --git a/android/src/app/organicmaps/widget/placepage/PlacePageViewModel.java b/android/src/app/organicmaps/widget/placepage/PlacePageViewModel.java
index be0241737d..fa8ed2f3d6 100644
--- a/android/src/app/organicmaps/widget/placepage/PlacePageViewModel.java
+++ b/android/src/app/organicmaps/widget/placepage/PlacePageViewModel.java
@@ -11,6 +11,8 @@ public class PlacePageViewModel extends ViewModel
{
private final MutableLiveData> mCurrentButtons = new MutableLiveData<>();
private final MutableLiveData mMapObject = new MutableLiveData<>();
+ private final MutableLiveData mPlacePageWidth = new MutableLiveData<>();
+ private final MutableLiveData mPlacePageDistanceToTop = new MutableLiveData<>();
public LiveData> getCurrentButtons()
{
@@ -31,4 +33,24 @@ public class PlacePageViewModel extends ViewModel
{
mMapObject.setValue(mapObject);
}
+
+ public MutableLiveData getPlacePageWidth()
+ {
+ return mPlacePageWidth;
+ }
+
+ public void setPlacePageWidth(int width)
+ {
+ mPlacePageWidth.setValue(width);
+ }
+
+ public MutableLiveData getPlacePageDistanceToTop()
+ {
+ return mPlacePageDistanceToTop;
+ }
+
+ public void setPlacePageDistanceToTop(int top)
+ {
+ mPlacePageDistanceToTop.setValue(top);
+ }
}
diff --git a/android/src/app/organicmaps/widget/placepage/sections/PlacePageBookmarkFragment.java b/android/src/app/organicmaps/widget/placepage/sections/PlacePageBookmarkFragment.java
index b400548424..db15d99893 100644
--- a/android/src/app/organicmaps/widget/placepage/sections/PlacePageBookmarkFragment.java
+++ b/android/src/app/organicmaps/widget/placepage/sections/PlacePageBookmarkFragment.java
@@ -75,16 +75,16 @@ public class PlacePageBookmarkFragment extends Fragment implements View.OnClickL
}
@Override
- public void onResume()
+ public void onStart()
{
- super.onResume();
+ super.onStart();
mViewModel.getMapObject().observe(requireActivity(), this);
}
@Override
- public void onPause()
+ public void onStop()
{
- super.onPause();
+ super.onStop();
mViewModel.getMapObject().removeObserver(this);
}
@@ -143,12 +143,12 @@ public class PlacePageBookmarkFragment extends Fragment implements View.OnClickL
}
@Override
- public void onChanged(MapObject mapObject)
+ public void onChanged(@Nullable MapObject mapObject)
{
// MapObject could be something else than a bookmark if the user already has the place page
// opened and clicks on a non-bookmarked POI.
// This callback would be called before the fragment had time to be destroyed
- if (mapObject.getMapObjectType() == MapObject.BOOKMARK)
+ if (mapObject != null && mapObject.getMapObjectType() == MapObject.BOOKMARK)
{
currentBookmark = (Bookmark) mapObject;
updateBookmarkDetails();
diff --git a/android/src/app/organicmaps/widget/placepage/sections/PlacePageLinksFragment.java b/android/src/app/organicmaps/widget/placepage/sections/PlacePageLinksFragment.java
index c7d1dee048..f552832bd6 100644
--- a/android/src/app/organicmaps/widget/placepage/sections/PlacePageLinksFragment.java
+++ b/android/src/app/organicmaps/widget/placepage/sections/PlacePageLinksFragment.java
@@ -218,23 +218,26 @@ public class PlacePageLinksFragment extends Fragment implements Observer {
PlacePageUtils.copyToClipboard(requireContext(), mFrame, TimeFormatUtils.formatTimetables(getResources(), ohStr, timetables));
@@ -173,7 +170,7 @@ public class PlacePageOpeningHoursFragment extends Fragment implements Observer<
// Show that place is closed today.
if (!containsCurrentWeekday)
{
- refreshTodayOpeningHours(resources.getString(R.string.day_off_today), ContextCompat.getColor(getContext(), R.color.base_red));
+ refreshTodayOpeningHours(resources.getString(R.string.day_off_today), ContextCompat.getColor(requireContext(), R.color.base_red));
UiUtils.hide(mTodayNonBusinessTime);
}
}
@@ -181,22 +178,23 @@ public class PlacePageOpeningHoursFragment extends Fragment implements Observer<
}
@Override
- public void onResume()
+ public void onStart()
{
- super.onResume();
+ super.onStart();
mViewModel.getMapObject().observe(requireActivity(), this);
}
@Override
- public void onPause()
+ public void onStop()
{
- super.onPause();
+ super.onStop();
mViewModel.getMapObject().removeObserver(this);
}
@Override
- public void onChanged(MapObject mapObject)
+ public void onChanged(@Nullable MapObject mapObject)
{
- refreshOpeningHours();
+ if (mapObject != null)
+ refreshOpeningHours(mapObject);
}
}
diff --git a/android/src/app/organicmaps/widget/placepage/sections/PlacePagePhoneFragment.java b/android/src/app/organicmaps/widget/placepage/sections/PlacePagePhoneFragment.java
index 52b432d1c1..fe4dacc56e 100644
--- a/android/src/app/organicmaps/widget/placepage/sections/PlacePagePhoneFragment.java
+++ b/android/src/app/organicmaps/widget/placepage/sections/PlacePagePhoneFragment.java
@@ -40,22 +40,23 @@ public class PlacePagePhoneFragment extends Fragment implements Observer