[android] Map fragments improvements #4808
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/coordinator"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -51,26 +50,9 @@
|
|||
android:paddingBottom="@dimen/margin_base"
|
||||
android:visibility="invisible" />
|
||||
</RelativeLayout>
|
||||
<androidx.core.widget.NestedScrollViewClickFixed
|
||||
android:id="@+id/placepage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="?attr/bottomSheetStyle"
|
||||
android:fillViewport="true"
|
||||
app:layout_behavior="@string/placepage_behavior" >
|
||||
<RelativeLayout
|
||||
android:id="@+id/placepage_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?panel" >
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/placepage_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</RelativeLayout>
|
||||
</androidx.core.widget.NestedScrollViewClickFixed>
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/pp_buttons_fragment"
|
||||
android:id="@+id/place_page_container_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent"
|
||||
android:name="app.organicmaps.widget.placepage.PlacePageController" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
29
android/res/layout/place_page_container_fragment.xml
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<androidx.core.widget.NestedScrollViewClickFixed
|
||||
android:id="@+id/placepage"
|
||||
style="?attr/bottomSheetStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fillViewport="true"
|
||||
app:layout_behavior="@string/placepage_behavior">
|
||||
<RelativeLayout
|
||||
android:id="@+id/placepage_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?panel">
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/placepage_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</RelativeLayout>
|
||||
</androidx.core.widget.NestedScrollViewClickFixed>
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/pp_buttons_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -27,6 +27,8 @@ import androidx.fragment.app.Fragment;
|
|||
import androidx.fragment.app.FragmentFactory;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import app.organicmaps.Framework.PlacePageActivationListener;
|
||||
import app.organicmaps.api.Const;
|
||||
import app.organicmaps.background.Notifier;
|
||||
|
@ -56,6 +58,7 @@ import app.organicmaps.location.LocationHelper;
|
|||
import app.organicmaps.location.LocationListener;
|
||||
import app.organicmaps.location.LocationState;
|
||||
import app.organicmaps.maplayer.MapButtonsController;
|
||||
import app.organicmaps.maplayer.MapButtonsViewModel;
|
||||
import app.organicmaps.maplayer.Mode;
|
||||
import app.organicmaps.maplayer.ToggleMapLayerFragment;
|
||||
import app.organicmaps.maplayer.isolines.IsolinesManager;
|
||||
|
@ -89,18 +92,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,
|
||||
|
@ -113,12 +113,10 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
RoutingBottomMenuListener,
|
||||
BookmarkManager.BookmarksLoadingListener,
|
||||
FloatingSearchToolbarController.SearchToolbarListener,
|
||||
PlacePageController.SlideListener,
|
||||
NoConnectionListener,
|
||||
MenuBottomSheetFragment.MenuBottomSheetInterfaceWithHeader,
|
||||
ToggleMapLayerFragment.LayerItemClickListener,
|
||||
PlacePageButtons.PlacePageButtonClickListener,
|
||||
PlacePageView.PlacePageViewListener
|
||||
PlacePageController.PlacePageRouteSettingsListener,
|
||||
MapButtonsController.MapButtonClickListener
|
||||
{
|
||||
private static final String TAG = MwmActivity.class.getSimpleName();
|
||||
|
||||
|
@ -133,8 +131,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
EditorHostFragment.class.getName(),
|
||||
ReportFragment.class.getName() };
|
||||
|
||||
private static final String EXTRA_CURRENT_LAYOUT_MODE = "CURRENT_LAYOUT_MODE";
|
||||
private static final String EXTRA_IS_FULLSCREEN = "IS_FULLSCREEN";
|
||||
public static final int REQ_CODE_ERROR_DRIVING_OPTIONS_DIALOG = 5;
|
||||
public static final int REQ_CODE_DRIVING_OPTIONS = 6;
|
||||
private static final int REQ_CODE_ISOLINES_ERROR = 8;
|
||||
|
@ -172,12 +168,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
private PanelAnimator mPanelAnimator;
|
||||
@Nullable
|
||||
private OnmapDownloader mOnmapDownloader;
|
||||
|
||||
@Nullable
|
||||
private MapButtonsController mMapButtonsController;
|
||||
|
||||
private boolean mIsTabletLayout;
|
||||
private boolean mIsFullscreen;
|
||||
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||
@NonNull
|
||||
private FloatingSearchToolbarController mSearchController;
|
||||
|
@ -185,15 +176,15 @@ 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;
|
||||
private MapButtonsViewModel mMapButtonsViewModel;
|
||||
private MapButtonsController.LayoutMode mPreviousMapLayoutMode;
|
||||
private Mode mPreviousLayerMode;
|
||||
|
||||
@Nullable
|
||||
private WindowInsetsCompat mCurrentWindowInsets;
|
||||
|
||||
|
@ -369,15 +360,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
protected void onSafeCreate(@Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onSafeCreate(savedInstanceState);
|
||||
if (savedInstanceState != null)
|
||||
{
|
||||
mCurrentLayoutMode = MapButtonsController.LayoutMode.values()[savedInstanceState.getInt(EXTRA_CURRENT_LAYOUT_MODE)];
|
||||
mIsFullscreen = savedInstanceState.getBoolean(EXTRA_IS_FULLSCREEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentLayoutMode = MapButtonsController.LayoutMode.regular;
|
||||
}
|
||||
mIsTabletLayout = getResources().getBoolean(R.bool.tabletLayout);
|
||||
|
||||
if (!mIsTabletLayout)
|
||||
|
@ -386,8 +368,13 @@ 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);
|
||||
mMapButtonsViewModel = new ViewModelProvider(this).get(MapButtonsViewModel.class);
|
||||
// We don't need to manually handle removing the observers it follows the activity lifecycle
|
||||
mMapButtonsViewModel.getBottomButtonsHeight().observe(this, this::onMapBottomButtonsHeightChange);
|
||||
mMapButtonsViewModel.getLayoutMode().observe(this, this::initNavigationButtons);
|
||||
mPreviousLayerMode = mMapButtonsViewModel.getMapLayerMode().getValue();
|
||||
mMapButtonsViewModel.getMapLayerMode().observe(this, this::onLayerChange);
|
||||
|
||||
mSearchController = new FloatingSearchToolbarController(this, this);
|
||||
mSearchController.getToolbar()
|
||||
|
@ -424,7 +411,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
UiUtils.setViewInsetsPaddingBottom(mPointChooser, windowInsets);
|
||||
UiUtils.setViewInsetsPaddingNoBottom(mPointChooserToolbar, windowInsets);
|
||||
|
||||
mNavBarHeight = mIsFullscreen ? 0 : windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
|
||||
mNavBarHeight = isFullscreen() ? 0 : windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
|
||||
// For the first loading, set compass top margin to status bar size
|
||||
// The top inset will be then be updated by the routing controller
|
||||
if (mCurrentWindowInsets == null)
|
||||
|
@ -465,7 +452,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
removeCurrentFragment(false);
|
||||
}
|
||||
|
||||
mNavigationController = new NavigationController(this, mMapButtonsController, v -> onSettingsOptionSelected(), this::updateBottomWidgetsOffset);
|
||||
mNavigationController = new NavigationController(this, v -> onSettingsOptionSelected(), this::updateBottomWidgetsOffset);
|
||||
//TrafficManager.INSTANCE.attach(mNavigationController);
|
||||
|
||||
initMainMenu();
|
||||
|
@ -565,7 +552,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
mPointChooserMode = mode;
|
||||
closeFloatingToolbarsAndPanels(false);
|
||||
UiUtils.show(mPointChooser);
|
||||
mMapButtonsController.showMapButtons(false);
|
||||
mMapButtonsViewModel.setButtonsHidden(true);
|
||||
Framework.nativeTurnOnChoosePositionMode(isBusiness, applyPosition);
|
||||
refreshLightStatusBar();
|
||||
}
|
||||
|
@ -574,7 +561,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
{
|
||||
UiUtils.hide(mPointChooser);
|
||||
Framework.nativeTurnOffChoosePositionMode();
|
||||
mMapButtonsController.showMapButtons(true);
|
||||
mMapButtonsViewModel.setButtonsHidden(false);
|
||||
if (mPointChooserMode == PointChooserMode.API)
|
||||
finish();
|
||||
mPointChooserMode = PointChooserMode.NONE;
|
||||
|
@ -613,32 +600,29 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
|
||||
private void initNavigationButtons()
|
||||
{
|
||||
initNavigationButtons(mCurrentLayoutMode);
|
||||
initNavigationButtons(mMapButtonsViewModel.getLayoutMode().getValue());
|
||||
}
|
||||
|
||||
private void initNavigationButtons(MapButtonsController.LayoutMode layoutMode)
|
||||
{
|
||||
if (mMapButtonsController == null || mMapButtonsController.getLayoutMode() != layoutMode)
|
||||
// Recreate the navigation buttons with the correct layout when it changes
|
||||
if (mPreviousMapLayoutMode != layoutMode)
|
||||
{
|
||||
mCurrentLayoutMode = layoutMode;
|
||||
|
||||
mMapButtonsController = new MapButtonsController();
|
||||
mMapButtonsController.init(
|
||||
layoutMode,
|
||||
LocationState.nativeGetMode(),
|
||||
this::onMapButtonClick,
|
||||
(v) -> closeSearchToolbar(true, true),
|
||||
mPlacePageController,
|
||||
this::updateBottomWidgetsOffset);
|
||||
|
||||
|
||||
FragmentTransaction transaction = getSupportFragmentManager()
|
||||
.beginTransaction().replace(R.id.map_buttons, mMapButtonsController);
|
||||
.beginTransaction().replace(R.id.map_buttons, new MapButtonsController());
|
||||
transaction.commit();
|
||||
mPreviousMapLayoutMode = layoutMode;
|
||||
}
|
||||
}
|
||||
|
||||
void onMapButtonClick(MapButtonsController.MapButtons button)
|
||||
@Override
|
||||
public void onSearchCanceled()
|
||||
{
|
||||
closeSearchToolbar(true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapButtonClick(MapButtonsController.MapButtons button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
|
@ -699,10 +683,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;
|
||||
}
|
||||
|
||||
|
@ -762,7 +746,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
if (stopSearch)
|
||||
{
|
||||
mSearchController.cancelSearchApiAndHide(clearText);
|
||||
mMapButtonsController.resetSearch();
|
||||
mMapButtonsViewModel.setSearchOption(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -829,7 +813,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
@Override
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState)
|
||||
{
|
||||
mPlacePageController.onSave(outState);
|
||||
if (!mIsTabletLayout && RoutingController.get().isPlanning())
|
||||
mRoutingPlanInplaceController.onSaveState(outState);
|
||||
|
||||
|
@ -843,8 +826,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
mNavigationController.onActivitySaveInstanceState(this, outState);
|
||||
|
||||
RoutingController.get().onSaveState();
|
||||
outState.putInt(EXTRA_CURRENT_LAYOUT_MODE, mCurrentLayoutMode.ordinal());
|
||||
outState.putBoolean(EXTRA_IS_FULLSCREEN, mIsFullscreen);
|
||||
|
||||
if (!isChangingConfigurations())
|
||||
RoutingController.get().saveRoute();
|
||||
|
@ -860,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);
|
||||
|
@ -991,11 +971,11 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
{
|
||||
super.onResume();
|
||||
refreshSearchToolbar();
|
||||
setFullscreen(mIsFullscreen);
|
||||
setFullscreen(isFullscreen());
|
||||
if (Framework.nativeIsInChoosePositionMode())
|
||||
{
|
||||
UiUtils.show(mPointChooser);
|
||||
mMapButtonsController.showMapButtons(false);
|
||||
mMapButtonsViewModel.setButtonsHidden(true);
|
||||
}
|
||||
if (mOnmapDownloader != null)
|
||||
mOnmapDownloader.onResume();
|
||||
|
@ -1070,8 +1050,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
{
|
||||
super.onSafeDestroy();
|
||||
mNavigationController.destroy();
|
||||
//TrafficManager.INSTANCE.detachAll();
|
||||
mPlacePageController.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1150,8 +1128,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.
|
||||
|
@ -1164,7 +1142,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
UiUtils.isVisible(mSearchController.getToolbar()))
|
||||
return;
|
||||
|
||||
setFullscreen(!mIsFullscreen);
|
||||
setFullscreen(!isFullscreen());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1179,15 +1157,14 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
|| RoutingController.get().isPlanning())
|
||||
return;
|
||||
|
||||
mIsFullscreen = isFullscreen;
|
||||
mMapButtonsController.showMapButtons(!isFullscreen);
|
||||
mMapButtonsViewModel.setButtonsHidden(isFullscreen);
|
||||
UiUtils.setFullscreen(this, isFullscreen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlacePageSlide(int top)
|
||||
private boolean isFullscreen()
|
||||
{
|
||||
mMapButtonsController.move(top);
|
||||
// Buttons are hidden in position chooser mode but we are not in fullscreen
|
||||
return Boolean.TRUE.equals(mMapButtonsViewModel.getButtonsHidden().getValue()) && !Framework.nativeIsInChoosePositionMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1222,6 +1199,10 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
Map.onCompassUpdated(north, true);
|
||||
}
|
||||
|
||||
public void onMapBottomButtonsHeightChange(float height) {
|
||||
updateBottomWidgetsOffset();
|
||||
}
|
||||
|
||||
public void updateBottomWidgetsOffset()
|
||||
{
|
||||
updateBottomWidgetsOffset(-1);
|
||||
|
@ -1233,8 +1214,9 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
return;
|
||||
|
||||
int offsetY = mNavBarHeight;
|
||||
if (mMapButtonsController != null)
|
||||
offsetY = Math.max(offsetY, (int) mMapButtonsController.getBottomButtonsHeight() + mNavBarHeight);
|
||||
final Float bottomButtonHeight = mMapButtonsViewModel.getBottomButtonsHeight().getValue();
|
||||
if (bottomButtonHeight != null)
|
||||
offsetY = Math.max(offsetY, bottomButtonHeight.intValue() + mNavBarHeight);
|
||||
if (mMainMenu != null)
|
||||
offsetY = Math.max(offsetY, mMainMenu.getMenuHeight());
|
||||
|
||||
|
@ -1271,17 +1253,17 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
{
|
||||
mNavigationController.show(true);
|
||||
closeSearchToolbar(false, false);
|
||||
mMainMenu.setState(MainMenu.State.NAVIGATION, mIsFullscreen);
|
||||
mMainMenu.setState(MainMenu.State.NAVIGATION, isFullscreen());
|
||||
return;
|
||||
}
|
||||
|
||||
if (RoutingController.get().isPlanning())
|
||||
{
|
||||
mMainMenu.setState(MainMenu.State.ROUTE_PREPARE, mIsFullscreen);
|
||||
mMainMenu.setState(MainMenu.State.ROUTE_PREPARE, isFullscreen());
|
||||
return;
|
||||
}
|
||||
|
||||
mMainMenu.setState(MainMenu.State.MENU, mIsFullscreen);
|
||||
mMainMenu.setState(MainMenu.State.MENU, isFullscreen());
|
||||
}
|
||||
|
||||
private boolean adjustMenuLineFrameVisibility()
|
||||
|
@ -1508,7 +1490,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
|
||||
mRoutingPlanInplaceController.hideDrivingOptionsView();
|
||||
mNavigationController.stop(this);
|
||||
initNavigationButtons(MapButtonsController.LayoutMode.regular);
|
||||
mMapButtonsViewModel.setSearchOption(null);
|
||||
mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.regular);
|
||||
refreshLightStatusBar();
|
||||
}
|
||||
|
||||
|
@ -1518,7 +1501,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
closeFloatingToolbarsAndPanels(true);
|
||||
ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
|
||||
mNavigationController.start(this);
|
||||
initNavigationButtons(MapButtonsController.LayoutMode.navigation);
|
||||
mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.navigation);
|
||||
refreshLightStatusBar();
|
||||
}
|
||||
|
||||
|
@ -1526,7 +1509,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
public void onPlanningCancelled()
|
||||
{
|
||||
closeFloatingToolbarsAndPanels(true);
|
||||
initNavigationButtons(MapButtonsController.LayoutMode.regular);
|
||||
mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.regular);
|
||||
refreshLightStatusBar();
|
||||
}
|
||||
|
||||
|
@ -1534,7 +1517,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
public void onPlanningStarted()
|
||||
{
|
||||
closeFloatingToolbarsAndPanels(true);
|
||||
initNavigationButtons(MapButtonsController.LayoutMode.planning);
|
||||
mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.planning);
|
||||
refreshLightStatusBar();
|
||||
}
|
||||
|
||||
|
@ -1544,7 +1527,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
closeFloatingToolbarsAndPanels(true);
|
||||
ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
|
||||
mNavigationController.stop(this);
|
||||
initNavigationButtons(MapButtonsController.LayoutMode.planning);
|
||||
mMapButtonsViewModel.setSearchOption(null);
|
||||
mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.planning);
|
||||
refreshLightStatusBar();
|
||||
}
|
||||
|
||||
|
@ -1607,7 +1591,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
public void onMyPositionModeChanged(int newMode)
|
||||
{
|
||||
Logger.d(TAG, "location newMode = " + newMode);
|
||||
mMapButtonsController.updateNavMyPositionButton(newMode);
|
||||
mMapButtonsViewModel.setMyPositionMode(newMode);
|
||||
RoutingController controller = RoutingController.get();
|
||||
if (controller.isPlanning())
|
||||
showAddStartOrFinishFrame(controller, true);
|
||||
|
@ -1783,12 +1767,11 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
shareMyLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayerItemClick(@NonNull Mode mode)
|
||||
public void onLayerChange(Mode mode)
|
||||
{
|
||||
closeFloatingPanels();
|
||||
if (mMapButtonsController != null)
|
||||
mMapButtonsController.toggleMapLayer(mode);
|
||||
if (mPreviousLayerMode != mode)
|
||||
closeFloatingPanels();
|
||||
mPreviousLayerMode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1812,8 +1795,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;
|
||||
}
|
||||
|
||||
|
@ -1826,30 +1807,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)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,10 @@ import androidx.annotation.Nullable;
|
|||
import androidx.annotation.OptIn;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import app.organicmaps.MwmActivity;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.downloader.MapManager;
|
||||
import app.organicmaps.downloader.UpdateInfo;
|
||||
|
@ -21,7 +25,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;
|
||||
|
@ -48,20 +52,28 @@ public class MapButtonsController extends Fragment
|
|||
private float mContentWidth;
|
||||
|
||||
private MapButtonClickListener mMapButtonClickListener;
|
||||
private View.OnClickListener mOnSearchCanceledListener;
|
||||
private PlacePageController mPlacePageController;
|
||||
private OnBottomButtonsHeightChangedListener mOnBottomButtonsHeightChangedListener;
|
||||
private PlacePageViewModel mPlacePageViewModel;
|
||||
private MapButtonsViewModel mMapButtonsViewModel;
|
||||
|
||||
private final Observer<Integer> mPlacePageDistanceToTopObserver = this::move;
|
||||
private final Observer<Boolean> mButtonHiddenObserver = this::setButtonsHidden;
|
||||
private final Observer<Integer> mMyPositionModeObserver = this::updateNavMyPositionButton;
|
||||
private final Observer<Mode> mMapLayerModeObserver = this::toggleMapLayer;
|
||||
private final Observer<SearchWheel.SearchOption> mSearchOptionObserver = this::onSearchOptionChange;
|
||||
|
||||
private LayoutMode mLayoutMode;
|
||||
private int mMyPositionMode;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
if (mLayoutMode == LayoutMode.navigation)
|
||||
final FragmentActivity activity = requireActivity();
|
||||
mMapButtonClickListener = (MwmActivity) activity;
|
||||
mPlacePageViewModel = new ViewModelProvider(activity).get(PlacePageViewModel.class);
|
||||
mMapButtonsViewModel = new ViewModelProvider(activity).get(MapButtonsViewModel.class);
|
||||
final LayoutMode layoutMode = mMapButtonsViewModel.getLayoutMode().getValue();
|
||||
if (layoutMode == LayoutMode.navigation)
|
||||
mFrame = inflater.inflate(R.layout.map_buttons_layout_navigation, container, false);
|
||||
else if (mLayoutMode == LayoutMode.planning)
|
||||
else if (layoutMode == LayoutMode.planning)
|
||||
mFrame = inflater.inflate(R.layout.map_buttons_layout_planning, container, false);
|
||||
else
|
||||
mFrame = inflater.inflate(R.layout.map_buttons_layout_regular, container, false);
|
||||
|
@ -75,44 +87,51 @@ public class MapButtonsController extends Fragment
|
|||
{
|
||||
helpButton.setImageResource(R.drawable.logo);
|
||||
// Keep this button colorful in normal theme.
|
||||
if (!ThemeUtils.isNightTheme(getContext()))
|
||||
if (!ThemeUtils.isNightTheme(requireContext()))
|
||||
helpButton.getDrawable().setTintList(null);
|
||||
}
|
||||
|
||||
final View zoomFrame = mFrame.findViewById(R.id.zoom_buttons_container);
|
||||
mFrame.findViewById(R.id.nav_zoom_in)
|
||||
.setOnClickListener((v) -> mMapButtonClickListener.onClick(MapButtons.zoomIn));
|
||||
.setOnClickListener((v) -> mMapButtonClickListener.onMapButtonClick(MapButtons.zoomIn));
|
||||
mFrame.findViewById(R.id.nav_zoom_out)
|
||||
.setOnClickListener((v) -> mMapButtonClickListener.onClick(MapButtons.zoomOut));
|
||||
.setOnClickListener((v) -> mMapButtonClickListener.onMapButtonClick(MapButtons.zoomOut));
|
||||
final View bookmarksButton = mFrame.findViewById(R.id.btn_bookmarks);
|
||||
bookmarksButton.setOnClickListener((v) -> mMapButtonClickListener.onClick(MapButtons.bookmarks));
|
||||
bookmarksButton.setOnClickListener((v) -> mMapButtonClickListener.onMapButtonClick(MapButtons.bookmarks));
|
||||
final View myPosition = mFrame.findViewById(R.id.my_position);
|
||||
mNavMyPosition = new MyPositionButton(myPosition, mMyPositionMode, (v) -> mMapButtonClickListener.onClick(MapButtons.myPosition));
|
||||
mNavMyPosition = new MyPositionButton(myPosition, (v) -> mMapButtonClickListener.onMapButtonClick(MapButtons.myPosition));
|
||||
|
||||
// Some buttons do not exist in navigation mode
|
||||
final FloatingActionButton layersButton = mFrame.findViewById(R.id.layers_button);
|
||||
if (layersButton != null)
|
||||
{
|
||||
mToggleMapLayerController = new MapLayersController(layersButton,
|
||||
() -> mMapButtonClickListener.onClick(MapButtons.toggleMapLayer), requireActivity());
|
||||
mToggleMapLayerController = new MapLayersController(
|
||||
layersButton,
|
||||
() -> mMapButtonClickListener.onMapButtonClick(MapButtons.toggleMapLayer),
|
||||
requireActivity(),
|
||||
mMapButtonsViewModel);
|
||||
}
|
||||
final View menuButton = mFrame.findViewById(R.id.menu_button);
|
||||
if (menuButton != null)
|
||||
{
|
||||
menuButton.setOnClickListener((v) -> mMapButtonClickListener.onClick(MapButtons.menu));
|
||||
menuButton.setOnClickListener((v) -> mMapButtonClickListener.onMapButtonClick(MapButtons.menu));
|
||||
// This hack is needed to show the badge on the initial startup. For some reason, updateMenuBadge does not work from onResume() there.
|
||||
menuButton.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
public void onGlobalLayout()
|
||||
{
|
||||
updateMenuBadge();
|
||||
menuButton.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (helpButton != null)
|
||||
helpButton.setOnClickListener((v) -> mMapButtonClickListener.onClick(MapButtons.help));
|
||||
helpButton.setOnClickListener((v) -> mMapButtonClickListener.onMapButtonClick(MapButtons.help));
|
||||
|
||||
mSearchWheel = new SearchWheel(mFrame, (v) -> mMapButtonClickListener.onClick(MapButtons.search), mOnSearchCanceledListener);
|
||||
mSearchWheel = new SearchWheel(mFrame,
|
||||
(v) -> mMapButtonClickListener.onMapButtonClick(MapButtons.search),
|
||||
(v) -> mMapButtonClickListener.onSearchCanceled(),
|
||||
mMapButtonsViewModel);
|
||||
final View searchButton = mFrame.findViewById(R.id.btn_search);
|
||||
|
||||
// Used to get the maximum height the buttons will evolve in
|
||||
|
@ -135,25 +154,9 @@ public class MapButtonsController extends Fragment
|
|||
UiUtils.setViewInsetsPadding(view, windowInsets);
|
||||
return windowInsets;
|
||||
});
|
||||
|
||||
return mFrame;
|
||||
}
|
||||
|
||||
public LayoutMode getLayoutMode()
|
||||
{
|
||||
return mLayoutMode;
|
||||
}
|
||||
|
||||
public void init(LayoutMode layoutMode, int myPositionMode, MapButtonClickListener mapButtonClickListener, @NonNull View.OnClickListener onSearchCanceledListener, PlacePageController placePageController, OnBottomButtonsHeightChangedListener onBottomButtonsHeightChangedListener)
|
||||
{
|
||||
mLayoutMode = layoutMode;
|
||||
mMyPositionMode = myPositionMode;
|
||||
mMapButtonClickListener = mapButtonClickListener;
|
||||
mOnSearchCanceledListener = onSearchCanceledListener;
|
||||
mPlacePageController = placePageController;
|
||||
mOnBottomButtonsHeightChangedListener = onBottomButtonsHeightChangedListener;
|
||||
}
|
||||
|
||||
public void showButton(boolean show, MapButtonsController.MapButtons button)
|
||||
{
|
||||
// TODO(AB): Why do we need this check? Isn't it better to crash and fix the wrong logic ASAP?
|
||||
|
@ -209,7 +212,12 @@ public class MapButtonsController extends Fragment
|
|||
|
||||
private boolean isBehindPlacePage(View v)
|
||||
{
|
||||
return !(mContentWidth / 2 > (mPlacePageController.getPlacePageWidth() / 2.0) + v.getWidth());
|
||||
if (mPlacePageViewModel == null)
|
||||
return false;
|
||||
final Integer placePageWidth = mPlacePageViewModel.getPlacePageWidth().getValue();
|
||||
if (placePageWidth != null)
|
||||
return !(mContentWidth / 2 > (placePageWidth.floatValue() / 2.0) + v.getWidth());
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isMoving(View v)
|
||||
|
@ -259,7 +267,7 @@ public class MapButtonsController extends Fragment
|
|||
}
|
||||
}
|
||||
|
||||
public float getBottomButtonsHeight()
|
||||
private float getBottomButtonsHeight()
|
||||
{
|
||||
if (mBottomButtonsFrame != null && mFrame != null && UiUtils.isVisible(mFrame))
|
||||
return mBottomButtonsFrame.getMeasuredHeight();
|
||||
|
@ -267,16 +275,12 @@ public class MapButtonsController extends Fragment
|
|||
return 0;
|
||||
}
|
||||
|
||||
public void showMapButtons(boolean show)
|
||||
public void setButtonsHidden(boolean buttonHidden)
|
||||
{
|
||||
if (show)
|
||||
{
|
||||
UiUtils.show(mFrame);
|
||||
UiUtils.showIf(!buttonHidden, mFrame);
|
||||
if (!buttonHidden)
|
||||
updateButtonsVisibility();
|
||||
}
|
||||
else
|
||||
UiUtils.hide(mFrame);
|
||||
mOnBottomButtonsHeightChangedListener.OnBottomButtonsHeightChanged();
|
||||
mMapButtonsViewModel.setBottomButtonsHeight(getBottomButtonsHeight());
|
||||
}
|
||||
|
||||
private boolean isInNavigationMode()
|
||||
|
@ -284,10 +288,15 @@ public class MapButtonsController extends Fragment
|
|||
return RoutingController.get().isPlanning() || RoutingController.get().isNavigating();
|
||||
}
|
||||
|
||||
public void toggleMapLayer(@NonNull Mode mode)
|
||||
public void toggleMapLayer(@Nullable Mode mode)
|
||||
{
|
||||
if (mToggleMapLayerController != null)
|
||||
mToggleMapLayerController.toggleMode(mode);
|
||||
{
|
||||
if (mode == null)
|
||||
mToggleMapLayerController.disableModes();
|
||||
else
|
||||
mToggleMapLayerController.enableMode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateNavMyPositionButton(int newMode)
|
||||
|
@ -301,6 +310,18 @@ public class MapButtonsController extends Fragment
|
|||
return (int) (translation + v.getTop());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
final FragmentActivity activity = requireActivity();
|
||||
mPlacePageViewModel.getPlacePageDistanceToTop().observe(activity, mPlacePageDistanceToTopObserver);
|
||||
mMapButtonsViewModel.getButtonsHidden().observe(activity, mButtonHiddenObserver);
|
||||
mMapButtonsViewModel.getMyPositionMode().observe(activity, mMyPositionModeObserver);
|
||||
mMapButtonsViewModel.getMapLayerMode().observe(activity, mMapLayerModeObserver);
|
||||
mMapButtonsViewModel.getSearchOption().observe(activity, mSearchOptionObserver);
|
||||
}
|
||||
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
|
@ -308,19 +329,21 @@ public class MapButtonsController extends Fragment
|
|||
updateMenuBadge();
|
||||
}
|
||||
|
||||
public void resetSearch()
|
||||
@Override
|
||||
public void onStop()
|
||||
{
|
||||
mSearchWheel.reset();
|
||||
super.onStop();
|
||||
mPlacePageViewModel.getPlacePageDistanceToTop().removeObserver(mPlacePageDistanceToTopObserver);
|
||||
mMapButtonsViewModel.getButtonsHidden().removeObserver(mButtonHiddenObserver);
|
||||
mMapButtonsViewModel.getMyPositionMode().removeObserver(mMyPositionModeObserver);
|
||||
mMapButtonsViewModel.getMapLayerMode().removeObserver(mMapLayerModeObserver);
|
||||
mMapButtonsViewModel.getSearchOption().removeObserver(mSearchOptionObserver);
|
||||
}
|
||||
|
||||
public void saveNavSearchState(@NonNull Bundle outState)
|
||||
public void onSearchOptionChange(@Nullable SearchWheel.SearchOption searchOption)
|
||||
{
|
||||
mSearchWheel.saveState(outState);
|
||||
}
|
||||
|
||||
public void restoreNavSearchState(@NonNull Bundle savedInstanceState)
|
||||
{
|
||||
mSearchWheel.restoreState(savedInstanceState);
|
||||
if (searchOption == null)
|
||||
mSearchWheel.reset();
|
||||
}
|
||||
|
||||
public enum LayoutMode
|
||||
|
@ -345,12 +368,9 @@ public class MapButtonsController extends Fragment
|
|||
|
||||
public interface MapButtonClickListener
|
||||
{
|
||||
void onClick(MapButtons button);
|
||||
}
|
||||
void onMapButtonClick(MapButtons button);
|
||||
|
||||
public interface OnBottomButtonsHeightChangedListener
|
||||
{
|
||||
void OnBottomButtonsHeightChanged();
|
||||
void onSearchCanceled();
|
||||
}
|
||||
|
||||
private class ContentViewLayoutChangeListener implements View.OnLayoutChangeListener
|
||||
|
@ -369,7 +389,7 @@ public class MapButtonsController extends Fragment
|
|||
{
|
||||
mContentHeight = bottom - top;
|
||||
mContentWidth = right - left;
|
||||
mOnBottomButtonsHeightChangedListener.OnBottomButtonsHeightChanged();
|
||||
mMapButtonsViewModel.setBottomButtonsHeight(getBottomButtonsHeight());
|
||||
mContentView.removeOnLayoutChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package app.organicmaps.maplayer;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
public class MapButtonsViewModel extends ViewModel
|
||||
{
|
||||
private final MutableLiveData<Boolean> mButtonsHidden = new MutableLiveData<>(false);
|
||||
private final MutableLiveData<Float> mBottomButtonsHeight = new MutableLiveData<>(0f);
|
||||
private final MutableLiveData<MapButtonsController.LayoutMode> mLayoutMode = new MutableLiveData<>(MapButtonsController.LayoutMode.regular);
|
||||
private final MutableLiveData<Integer> mMyPositionMode = new MutableLiveData<>();
|
||||
private final MutableLiveData<Mode> mMapLayerMode = new MutableLiveData<>();
|
||||
private final MutableLiveData<SearchWheel.SearchOption> mSearchOption = new MutableLiveData<>();
|
||||
![]() Here is the documentation: https://developer.android.com/topic/libraries/architecture/livedata#java. This is a lifecycle aware observable value. When you create the view model, you tie it to an activity. Then the live data inside that view model follows the activity life cycle, so it does not trigger callbacks when the activity is stopped and automatically removes listeners when it is destroyed. In our case, when we use the viewmodels in fragments we still have to remove the listeners because they have a shorter life cycle than the parent activity (to prevent the listeners from trying to update a destroyed UI). Tying the view model to the parent activity allows us the reuse the value across different fragments. So the viewmodels store the UI state, and fragments can simply observe the live data to update their UI. No more This makes debugging a lot easier and makes the codebase more robust. But then again I am no Android expert. Here is the documentation: https://developer.android.com/topic/libraries/architecture/livedata#java.
**This is a lifecycle aware observable value**. When you create the view model, you tie it to an activity. Then the live data inside that view model follows the activity life cycle, so it does not trigger callbacks when the activity is stopped and automatically removes listeners when it is destroyed.
In our case, when we use the viewmodels in fragments we still have to remove the listeners because they have a shorter life cycle than the parent activity (to prevent the listeners from trying to update a destroyed UI).
Tying the view model to the parent activity allows us the reuse the value across different fragments. So the viewmodels store the UI state, and fragments can simply observe the live data to update their UI. No more `onSavedInstanceState`, no more dependency injection all over the place and we are sure all the fragments use the same state.
This makes debugging a lot easier and makes the codebase more robust. But then again I am no Android expert.
|
||||
|
||||
public MutableLiveData<Boolean> getButtonsHidden()
|
||||
{
|
||||
return mButtonsHidden;
|
||||
}
|
||||
|
||||
public void setButtonsHidden(boolean buttonsHidden)
|
||||
{
|
||||
mButtonsHidden.setValue(buttonsHidden);
|
||||
}
|
||||
|
||||
public MutableLiveData<Float> getBottomButtonsHeight()
|
||||
{
|
||||
return mBottomButtonsHeight;
|
||||
}
|
||||
|
||||
public void setBottomButtonsHeight(float height)
|
||||
{
|
||||
mBottomButtonsHeight.setValue(height);
|
||||
}
|
||||
|
||||
public MutableLiveData<MapButtonsController.LayoutMode> getLayoutMode()
|
||||
{
|
||||
return mLayoutMode;
|
||||
}
|
||||
|
||||
public void setLayoutMode(MapButtonsController.LayoutMode layoutMode)
|
||||
{
|
||||
mLayoutMode.setValue(layoutMode);
|
||||
}
|
||||
|
||||
public MutableLiveData<Integer> getMyPositionMode()
|
||||
{
|
||||
return mMyPositionMode;
|
||||
}
|
||||
|
||||
public void setMyPositionMode(int mode)
|
||||
{
|
||||
mMyPositionMode.setValue(mode);
|
||||
}
|
||||
|
||||
public MutableLiveData<Mode> getMapLayerMode()
|
||||
{
|
||||
return mMapLayerMode;
|
||||
}
|
||||
|
||||
public void setMapLayerMode(Mode mode)
|
||||
{
|
||||
mMapLayerMode.setValue(mode);
|
||||
}
|
||||
|
||||
public MutableLiveData<SearchWheel.SearchOption> getSearchOption()
|
||||
{
|
||||
return mSearchOption;
|
||||
}
|
||||
|
||||
public void setSearchOption(@Nullable SearchWheel.SearchOption searchOption)
|
||||
{
|
||||
mSearchOption.setValue(searchOption);
|
||||
}
|
||||
}
|
|
@ -23,21 +23,19 @@ public class MapLayersController
|
|||
OnShowMenuListener mOnShowMenuListener;
|
||||
@NonNull
|
||||
private Mode mCurrentLayer;
|
||||
private final MapButtonsViewModel mMapButtonsViewModel;
|
||||
|
||||
public MapLayersController(@NonNull ImageButton layersButton, @NonNull OnShowMenuListener onShowMenuListener, @NonNull Activity activity)
|
||||
public MapLayersController(@NonNull ImageButton layersButton, @NonNull OnShowMenuListener onShowMenuListener, @NonNull Activity activity, MapButtonsViewModel mapButtonsViewModel)
|
||||
{
|
||||
mActivity = activity;
|
||||
mMapButtonsViewModel = mapButtonsViewModel;
|
||||
mLayersButton = layersButton;
|
||||
mLayersButton.setOnClickListener(view -> onLayersButtonClick());
|
||||
mOnShowMenuListener = onShowMenuListener;
|
||||
mLayers = LayersUtils.getAvailableLayers();
|
||||
mCurrentLayer = getCurrentLayer();
|
||||
initMode();
|
||||
}
|
||||
|
||||
private void initMode()
|
||||
{
|
||||
setEnabled(mCurrentLayer.isEnabled(mActivity));
|
||||
// View model only expects a layer if it is active
|
||||
mMapButtonsViewModel.setMapLayerMode(mCurrentLayer.isEnabled(activity) ? mCurrentLayer : null);
|
||||
showButton(true);
|
||||
}
|
||||
|
||||
|
@ -76,16 +74,21 @@ public class MapLayersController
|
|||
private void onLayersButtonClick()
|
||||
{
|
||||
if (mCurrentLayer.isEnabled(mActivity))
|
||||
setEnabled(false);
|
||||
mMapButtonsViewModel.setMapLayerMode(null);
|
||||
else
|
||||
mOnShowMenuListener.onShow();
|
||||
}
|
||||
|
||||
public void toggleMode(@NonNull Mode mode)
|
||||
public void disableModes()
|
||||
{
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
public void enableMode(@NonNull Mode mode)
|
||||
{
|
||||
setCurrentLayer(mode);
|
||||
showButton(true);
|
||||
setEnabled(!mode.isEnabled(mActivity));
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
public void showButton(boolean show)
|
||||
|
|
|
@ -26,7 +26,6 @@ import app.organicmaps.util.concurrency.UiThread;
|
|||
|
||||
public class SearchWheel implements View.OnClickListener
|
||||
{
|
||||
private static final String EXTRA_CURRENT_OPTION = "extra_current_option";
|
||||
private final View mFrame;
|
||||
|
||||
private View mSearchLayout;
|
||||
|
@ -35,12 +34,11 @@ public class SearchWheel implements View.OnClickListener
|
|||
private final View mTouchInterceptor;
|
||||
|
||||
private boolean mIsExpanded;
|
||||
@Nullable
|
||||
private SearchOption mCurrentOption;
|
||||
@NonNull
|
||||
private final View.OnClickListener mOnSearchPressedListener;
|
||||
@NonNull
|
||||
private final View.OnClickListener mOnSearchCanceledListener;
|
||||
private MapButtonsViewModel mMapButtonsViewModel;
|
||||
|
||||
private static final long CLOSE_DELAY_MILLIS = 5000L;
|
||||
private final Runnable mCloseRunnable = new Runnable() {
|
||||
|
@ -55,7 +53,7 @@ public class SearchWheel implements View.OnClickListener
|
|||
}
|
||||
};
|
||||
|
||||
private enum SearchOption
|
||||
public enum SearchOption
|
||||
{
|
||||
FUEL(R.id.search_fuel, R.drawable.ic_routing_fuel_off, R.string.fuel),
|
||||
PARKING(R.id.search_parking, R.drawable.ic_routing_parking_off, R.string.parking),
|
||||
|
@ -103,9 +101,11 @@ public class SearchWheel implements View.OnClickListener
|
|||
}
|
||||
}
|
||||
|
||||
public SearchWheel(View frame, @NonNull View.OnClickListener onSearchPressedListener, @NonNull View.OnClickListener onSearchCanceledListener)
|
||||
public SearchWheel(View frame, @NonNull View.OnClickListener onSearchPressedListener,
|
||||
@NonNull View.OnClickListener onSearchCanceledListener, MapButtonsViewModel mapButtonsViewModel)
|
||||
{
|
||||
mFrame = frame;
|
||||
mMapButtonsViewModel = mapButtonsViewModel;
|
||||
mOnSearchPressedListener = onSearchPressedListener;
|
||||
mOnSearchCanceledListener = onSearchCanceledListener;
|
||||
mTouchInterceptor = mFrame.findViewById(R.id.touch_interceptor);
|
||||
|
@ -151,26 +151,15 @@ public class SearchWheel implements View.OnClickListener
|
|||
UiUtils.showIf(show && mIsExpanded, mSearchLayout);
|
||||
}
|
||||
|
||||
public void saveState(@NonNull Bundle outState)
|
||||
{
|
||||
outState.putSerializable(EXTRA_CURRENT_OPTION, mCurrentOption);
|
||||
}
|
||||
|
||||
public void restoreState(@NonNull Bundle savedState)
|
||||
{
|
||||
mCurrentOption = Utils.getSerializable(savedState, EXTRA_CURRENT_OPTION, SearchOption.class);
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
mIsExpanded = false;
|
||||
mCurrentOption = null;
|
||||
resetSearchButtonImage();
|
||||
}
|
||||
|
||||
public void onResume()
|
||||
{
|
||||
if (mCurrentOption != null)
|
||||
if (mMapButtonsViewModel.getSearchOption().getValue() != null)
|
||||
{
|
||||
refreshSearchButtonImage();
|
||||
return;
|
||||
|
@ -183,7 +172,6 @@ public class SearchWheel implements View.OnClickListener
|
|||
return;
|
||||
}
|
||||
|
||||
mCurrentOption = SearchOption.fromSearchQuery(query, mFrame.getContext());
|
||||
refreshSearchButtonImage();
|
||||
}
|
||||
|
||||
|
@ -244,10 +232,11 @@ public class SearchWheel implements View.OnClickListener
|
|||
|
||||
private void refreshSearchButtonImage()
|
||||
{
|
||||
final SearchOption searchOption = mMapButtonsViewModel.getSearchOption().getValue();
|
||||
mSearchButton.setImageDrawable(Graphics.tint(mSearchButton.getContext(),
|
||||
mCurrentOption == null ?
|
||||
searchOption == null ?
|
||||
R.drawable.ic_routing_search_off :
|
||||
mCurrentOption.mDrawableOff,
|
||||
searchOption.mDrawableOff,
|
||||
R.attr.colorAccent));
|
||||
}
|
||||
|
||||
|
@ -278,7 +267,7 @@ public class SearchWheel implements View.OnClickListener
|
|||
return;
|
||||
}
|
||||
|
||||
if (mCurrentOption != null || !TextUtils.isEmpty(SearchEngine.INSTANCE.getQuery()))
|
||||
if (mMapButtonsViewModel.getSearchOption().getValue() != null || !TextUtils.isEmpty(SearchEngine.INSTANCE.getQuery()))
|
||||
{
|
||||
mOnSearchCanceledListener.onClick(v);
|
||||
refreshSearchVisibility();
|
||||
|
@ -303,7 +292,7 @@ public class SearchWheel implements View.OnClickListener
|
|||
|
||||
private void startSearch(SearchOption searchOption)
|
||||
{
|
||||
mCurrentOption = searchOption;
|
||||
mMapButtonsViewModel.setSearchOption(searchOption);
|
||||
final String query = mFrame.getContext().getString(searchOption.mQueryId);
|
||||
// Category request from navigation search wheel.
|
||||
SearchEngine.INSTANCE.searchInteractive(mFrame.getContext(), query, true, System.nanoTime(), false);
|
||||
|
|
|
@ -9,24 +9,23 @@ import android.view.ViewGroup;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.maplayer.isolines.IsolinesManager;
|
||||
import app.organicmaps.widget.recycler.SpanningLinearLayoutManager;
|
||||
import app.organicmaps.util.SharedPropertiesUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.widget.recycler.SpanningLinearLayoutManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ToggleMapLayerFragment extends Fragment
|
||||
{
|
||||
@Nullable
|
||||
private LayerItemClickListener mLayerItemClickListener;
|
||||
@Nullable
|
||||
private LayersAdapter mAdapter;
|
||||
private MapButtonsViewModel mMapButtonsViewModel;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
@ -34,8 +33,7 @@ public class ToggleMapLayerFragment extends Fragment
|
|||
{
|
||||
View mRoot = inflater.inflate(R.layout.fragment_toggle_map_layer, container, false);
|
||||
|
||||
if (requireActivity() instanceof LayerItemClickListener)
|
||||
mLayerItemClickListener = ((LayerItemClickListener) requireActivity());
|
||||
mMapButtonsViewModel = new ViewModelProvider(requireActivity()).get(MapButtonsViewModel.class);
|
||||
|
||||
initRecycler(mRoot);
|
||||
return mRoot;
|
||||
|
@ -72,12 +70,6 @@ public class ToggleMapLayerFragment extends Fragment
|
|||
mAdapter.notifyDataSetChanged();
|
||||
if (IsolinesManager.from(context).shouldShowNotification())
|
||||
Utils.showSnackbar(context, v.getRootView(), R.string.isolines_toast_zooms_1_10);
|
||||
if (mLayerItemClickListener != null)
|
||||
mLayerItemClickListener.onLayerItemClick(mode);
|
||||
}
|
||||
|
||||
public interface LayerItemClickListener
|
||||
{
|
||||
void onLayerItemClick(@NonNull Mode mode);
|
||||
mMapButtonsViewModel.setMapLayerMode(mode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,17 +21,16 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
import app.organicmaps.Framework;
|
||||
import app.organicmaps.MwmActivity;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.base.MediaPlayerWrapper;
|
||||
import app.organicmaps.maplayer.MapButtonsController;
|
||||
import app.organicmaps.maplayer.traffic.TrafficManager;
|
||||
import app.organicmaps.sound.TtsPlayer;
|
||||
import app.organicmaps.widget.menu.NavMenu;
|
||||
import app.organicmaps.util.UiUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.widget.menu.NavMenu;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
@ -59,10 +58,7 @@ public class NavigationController implements Application.ActivityLifecycleCallba
|
|||
private final RecyclerView mLanes;
|
||||
@NonNull
|
||||
private final LanesAdapter mLanesAdapter;
|
||||
|
||||
@NonNull
|
||||
private final MapButtonsController mMapButtonsController;
|
||||
|
||||
|
||||
@NonNull
|
||||
private final MediaPlayer.OnCompletionListener mSpeedCamSignalCompletionListener;
|
||||
|
||||
|
@ -106,13 +102,12 @@ public class NavigationController implements Application.ActivityLifecycleCallba
|
|||
mLanes.setNestedScrollingEnabled(false);
|
||||
}
|
||||
|
||||
public NavigationController(AppCompatActivity activity, @NonNull MapButtonsController mapButtonsController,
|
||||
View.OnClickListener onSettingsClickListener, NavMenu.OnMenuSizeChangedListener onMenuSizeChangedListener)
|
||||
public NavigationController(AppCompatActivity activity, View.OnClickListener onSettingsClickListener,
|
||||
NavMenu.OnMenuSizeChangedListener onMenuSizeChangedListener)
|
||||
{
|
||||
mFrame = activity.findViewById(R.id.navigation_frame);
|
||||
mNavMenu = new NavMenu(activity, this, onMenuSizeChangedListener);
|
||||
mOnSettingsClickListener = onSettingsClickListener;
|
||||
mMapButtonsController = mapButtonsController;
|
||||
|
||||
// Top frame
|
||||
View topFrame = mFrame.findViewById(R.id.nav_top_frame);
|
||||
|
@ -154,8 +149,6 @@ public class NavigationController implements Application.ActivityLifecycleCallba
|
|||
|
||||
public void stop(MwmActivity parent)
|
||||
{
|
||||
mMapButtonsController.resetSearch();
|
||||
|
||||
if (mBound)
|
||||
{
|
||||
parent.unbindService(mServiceConnection);
|
||||
|
@ -330,7 +323,6 @@ public class NavigationController implements Application.ActivityLifecycleCallba
|
|||
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState)
|
||||
{
|
||||
outState.putBoolean(STATE_BOUND, mBound);
|
||||
mMapButtonsController.saveNavSearchState(outState);
|
||||
}
|
||||
|
||||
public void onRestoreState(@NonNull Bundle savedInstanceState, @NonNull MwmActivity parent)
|
||||
|
@ -338,7 +330,6 @@ public class NavigationController implements Application.ActivityLifecycleCallba
|
|||
mBound = savedInstanceState.getBoolean(STATE_BOUND);
|
||||
if (mBound)
|
||||
start(parent);
|
||||
mMapButtonsController.restoreNavSearchState(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,13 +30,13 @@ public class MyPositionButton
|
|||
|
||||
private final int mFollowPaddingShift;
|
||||
|
||||
public MyPositionButton(@NonNull View button, int myPositionMode, @NonNull View.OnClickListener listener)
|
||||
public MyPositionButton(@NonNull View button, @NonNull View.OnClickListener listener)
|
||||
{
|
||||
mButton = (FloatingActionButton) button;
|
||||
mButton.setOnClickListener(listener);
|
||||
mIcons.clear();
|
||||
mFollowPaddingShift = (int) (FOLLOW_SHIFT * button.getResources().getDisplayMetrics().density);
|
||||
update(myPositionMode);
|
||||
update(LocationState.nativeGetMode());
|
||||
}
|
||||
|
||||
public void update(int mode)
|
||||
|
|
|
@ -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<List<Pl
|
|||
return windowInsets;
|
||||
});
|
||||
mMaxButtons = getResources().getInteger(R.integer.pp_buttons_max);
|
||||
mViewModel.getCurrentButtons().observe(requireActivity(), this);
|
||||
|
||||
Fragment parentFragment = getParentFragment();
|
||||
mItemListener = (PlacePageButtonClickListener) parentFragment;
|
||||
|
||||
createButtons(mViewModel.getCurrentButtons().getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context)
|
||||
public void onStart()
|
||||
{
|
||||
super.onAttach(context);
|
||||
try
|
||||
{
|
||||
mItemListener = (PlacePageButtonClickListener) context;
|
||||
}
|
||||
catch (ClassCastException e)
|
||||
{
|
||||
throw new ClassCastException(context + " must implement PlacePageButtonClickListener");
|
||||
}
|
||||
super.onStart();
|
||||
mViewModel.getCurrentButtons().observe(requireActivity(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView()
|
||||
public void onStop()
|
||||
{
|
||||
super.onDestroyView();
|
||||
super.onStop();
|
||||
mViewModel.getCurrentButtons().removeObserver(this);
|
||||
}
|
||||
|
||||
|
@ -94,7 +89,7 @@ public final class PlacePageButtons extends Fragment implements Observer<List<Pl
|
|||
private void showMoreBottomSheet()
|
||||
{
|
||||
MenuBottomSheetFragment.newInstance(PLACEPAGE_MORE_MENU_ID)
|
||||
.show(requireActivity().getSupportFragmentManager(), PLACEPAGE_MORE_MENU_ID);
|
||||
.show(getParentFragmentManager(), PLACEPAGE_MORE_MENU_ID);
|
||||
}
|
||||
|
||||
private void createButtons(@Nullable List<ButtonType> buttons)
|
||||
|
|
|
@ -1,101 +1,87 @@
|
|||
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<Activity>,
|
||||
Savable<Bundle>,
|
||||
PlacePageView.PlacePageViewListener,
|
||||
PlacePageButtons.PlacePageButtonClickListener,
|
||||
MenuBottomSheetFragment.MenuBottomSheetInterface,
|
||||
Observer<MapObject>
|
||||
public class PlacePageController extends Fragment implements
|
||||
PlacePageView.PlacePageViewListener,
|
||||
PlacePageButtons.PlacePageButtonClickListener,
|
||||
MenuBottomSheetFragment.MenuBottomSheetInterface,
|
||||
Observer<MapObject>
|
||||
{
|
||||
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<View> 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<View> 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;
|
||||
|
||||
PlacePageUtils.moveViewportUp(mPlacePage, mViewportMinHeight);
|
||||
PlacePageUtils.updateMapViewport(mCoordinator, mDistanceToTop, mViewportMinHeight);
|
||||
|
||||
if (PlacePageUtils.isHiddenState(newState))
|
||||
onHiddenInternal();
|
||||
|
@ -104,51 +90,48 @@ public class PlacePageController implements Initializable<Activity>,
|
|||
@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<Activity>,
|
|||
|
||||
private void onHiddenInternal()
|
||||
{
|
||||
if (mDeactivateMapSelection)
|
||||
Framework.nativeDeactivatePopup();
|
||||
mDeactivateMapSelection = true;
|
||||
PlacePageUtils.moveViewportUp(mPlacePage, mViewportMinHeight);
|
||||
Framework.nativeDeactivatePopup();
|
||||
PlacePageUtils.updateMapViewport(mCoordinator, mDistanceToTop, mViewportMinHeight);
|
||||
resetPlacePageHeightBounds();
|
||||
removePlacePageFragments();
|
||||
}
|
||||
|
||||
public int getPlacePageWidth()
|
||||
{
|
||||
return mPlacePage.getWidth();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ArrayList<MenuBottomSheetItem> getMenuBottomSheetItems(String id)
|
||||
{
|
||||
|
@ -203,24 +179,27 @@ public class PlacePageController implements Initializable<Activity>,
|
|||
ArrayList<MenuBottomSheetItem> 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,10 +278,10 @@ public class PlacePageController implements Initializable<Activity>,
|
|||
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);
|
||||
PlacePageUtils.updateMapViewport(mCoordinator, mDistanceToTop, mViewportMinHeight);
|
||||
setPlacePageHeightBounds();
|
||||
}
|
||||
});
|
||||
|
@ -317,37 +296,12 @@ public class PlacePageController implements Initializable<Activity>,
|
|||
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<Activity>,
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlacePageRequestClose()
|
||||
{
|
||||
close(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlacePageRequestToggleState()
|
||||
{
|
||||
|
@ -375,24 +323,150 @@ public class PlacePageController implements Initializable<Activity>,
|
|||
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<Activity>,
|
|||
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<Activity>,
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package app.organicmaps.widget.placepage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.PopupMenu;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -15,20 +13,14 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
class PlacePageUtils
|
||||
public class PlacePageUtils
|
||||
{
|
||||
static void moveViewportUp(@NonNull View placePageView, int viewportMinHeight)
|
||||
static void updateMapViewport(@NonNull View parent, int placePageDistanceToTop, int viewportMinHeight)
|
||||
{
|
||||
placePageView.post(() -> {
|
||||
final View coordinatorLayout = (ViewGroup) placePageView.getParent();
|
||||
final int viewPortWidth = coordinatorLayout.getWidth();
|
||||
int viewPortHeight = coordinatorLayout.getHeight();
|
||||
Rect sheetRect = new Rect();
|
||||
placePageView.getGlobalVisibleRect(sheetRect);
|
||||
|
||||
viewPortHeight -= sheetRect.height();
|
||||
if (viewPortHeight >= viewportMinHeight)
|
||||
Framework.nativeSetVisibleRect(0, 0, viewPortWidth, viewPortHeight);
|
||||
parent.post(() -> {
|
||||
final int screenWidth = parent.getWidth();
|
||||
if (placePageDistanceToTop >= viewportMinHeight)
|
||||
Framework.nativeSetVisibleRect(0, 0, screenWidth, placePageDistanceToTop);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -84,7 +76,7 @@ class PlacePageUtils
|
|||
}
|
||||
}
|
||||
|
||||
static void copyToClipboard(Context context, View frame, String text)
|
||||
public static void copyToClipboard(Context context, View frame, String text)
|
||||
{
|
||||
Utils.copyTextToClipboard(context, text);
|
||||
Utils.showSnackbarAbove(frame,
|
||||
|
@ -92,7 +84,7 @@ class PlacePageUtils
|
|||
context.getString(R.string.copied_to_clipboard, text));
|
||||
}
|
||||
|
||||
static void showCopyPopup(Context context, View popupAnchor, View frame, List<String> items)
|
||||
public static void showCopyPopup(Context context, View popupAnchor, View frame, List<String> items)
|
||||
{
|
||||
final PopupMenu popup = new PopupMenu(context, popupAnchor);
|
||||
final Menu menu = popup.getMenu();
|
||||
|
|
|
@ -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,12 +37,15 @@ 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;
|
||||
import app.organicmaps.widget.ArrowView;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageBookmarkFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageLinksFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageOpeningHoursFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePagePhoneFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageWikipediaFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -58,7 +56,6 @@ import static android.view.View.VISIBLE;
|
|||
|
||||
public class PlacePageView extends Fragment implements View.OnClickListener,
|
||||
View.OnLongClickListener,
|
||||
PlacePageButtons.PlacePageButtonClickListener,
|
||||
LocationListener,
|
||||
Observer<MapObject>
|
||||
|
||||
|
@ -176,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());
|
||||
|
||||
|
@ -238,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);
|
||||
|
@ -450,7 +294,7 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
|
|||
fm.beginTransaction()
|
||||
.setReorderingAllowed(true)
|
||||
.remove(fragment)
|
||||
.commitNow();
|
||||
.commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -499,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);
|
||||
|
@ -753,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();
|
||||
|
@ -773,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
|
||||
|
@ -782,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();
|
||||
|
@ -810,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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ public class PlacePageViewModel extends ViewModel
|
|||
{
|
||||
private final MutableLiveData<List<PlacePageButtons.ButtonType>> mCurrentButtons = new MutableLiveData<>();
|
||||
private final MutableLiveData<MapObject> mMapObject = new MutableLiveData<>();
|
||||
private final MutableLiveData<Integer> mPlacePageWidth = new MutableLiveData<>();
|
||||
private final MutableLiveData<Integer> mPlacePageDistanceToTop = new MutableLiveData<>();
|
||||
![]() Same here, why MutableLiveData ? Same here, why MutableLiveData ?
|
||||
|
||||
public LiveData<List<PlacePageButtons.ButtonType>> getCurrentButtons()
|
||||
{
|
||||
|
@ -31,4 +33,24 @@ public class PlacePageViewModel extends ViewModel
|
|||
{
|
||||
mMapObject.setValue(mapObject);
|
||||
}
|
||||
|
||||
public MutableLiveData<Integer> getPlacePageWidth()
|
||||
{
|
||||
return mPlacePageWidth;
|
||||
}
|
||||
|
||||
public void setPlacePageWidth(int width)
|
||||
{
|
||||
mPlacePageWidth.setValue(width);
|
||||
}
|
||||
|
||||
public MutableLiveData<Integer> getPlacePageDistanceToTop()
|
||||
{
|
||||
return mPlacePageDistanceToTop;
|
||||
}
|
||||
|
||||
public void setPlacePageDistanceToTop(int top)
|
||||
{
|
||||
mPlacePageDistanceToTop.setValue(top);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package app.organicmaps.widget.placepage;
|
||||
package app.organicmaps.widget.placepage.sections;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
|
@ -1,4 +1,4 @@
|
|||
package app.organicmaps.widget.placepage;
|
||||
package app.organicmaps.widget.placepage.sections;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
@ -26,6 +26,8 @@ import app.organicmaps.bookmarks.data.MapObject;
|
|||
import app.organicmaps.util.StringUtils;
|
||||
import app.organicmaps.util.UiUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.widget.placepage.EditBookmarkFragment;
|
||||
import app.organicmaps.widget.placepage.PlacePageViewModel;
|
||||
|
||||
public class PlacePageBookmarkFragment extends Fragment implements View.OnClickListener,
|
||||
View.OnLongClickListener,
|
||||
|
@ -73,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);
|
||||
}
|
||||
|
||||
|
@ -141,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();
|
|
@ -1,4 +1,4 @@
|
|||
package app.organicmaps.widget.placepage;
|
||||
package app.organicmaps.widget.placepage.sections;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
@ -17,6 +17,8 @@ import app.organicmaps.R;
|
|||
import app.organicmaps.bookmarks.data.MapObject;
|
||||
import app.organicmaps.bookmarks.data.Metadata;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.widget.placepage.PlacePageUtils;
|
||||
import app.organicmaps.widget.placepage.PlacePageViewModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -216,23 +218,26 @@ public class PlacePageLinksFragment extends Fragment implements Observer<MapObje
|
|||
}
|
||||
|
||||
@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)
|
||||
{
|
||||
mMapObject = mapObject;
|
||||
refreshLinks();
|
||||
if (mapObject != null)
|
||||
{
|
||||
mMapObject = mapObject;
|
||||
refreshLinks();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package app.organicmaps.widget.placepage;
|
||||
package app.organicmaps.widget.placepage.sections;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
|
@ -25,6 +25,8 @@ import app.organicmaps.editor.data.Timetable;
|
|||
import app.organicmaps.util.ThemeUtils;
|
||||
import app.organicmaps.util.UiUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.widget.placepage.PlacePageUtils;
|
||||
import app.organicmaps.widget.placepage.PlacePageViewModel;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
@ -88,11 +90,9 @@ public class PlacePageOpeningHoursFragment extends Fragment implements Observer<
|
|||
mTodayOpenTime.setTextColor(color);
|
||||
}
|
||||
|
||||
private void refreshOpeningHours()
|
||||
private void refreshOpeningHours(MapObject mapObject)
|
||||
{
|
||||
final String ohStr = mViewModel.getMapObject()
|
||||
.getValue()
|
||||
.getMetadata(Metadata.MetadataType.FMD_OPEN_HOURS);
|
||||
final String ohStr = mapObject.getMetadata(Metadata.MetadataType.FMD_OPEN_HOURS);
|
||||
final Timetable[] timetables = OpeningHours.nativeTimetablesFromString(ohStr);
|
||||
mFrame.setOnLongClickListener((v) -> {
|
||||
PlacePageUtils.copyToClipboard(requireContext(), mFrame, TimeFormatUtils.formatTimetables(getResources(), ohStr, timetables));
|
||||
|
@ -170,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);
|
||||
}
|
||||
}
|
||||
|
@ -178,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);
|
||||
![]()
```suggestion
if (mapObject != null)
refreshOpeningHours(mapObject);
```
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged(MapObject mapObject)
|
||||
public void onChanged(@Nullable MapObject mapObject)
|
||||
{
|
||||
refreshOpeningHours();
|
||||
if (mapObject != null)
|
||||
refreshOpeningHours(mapObject);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package app.organicmaps.widget.placepage;
|
||||
package app.organicmaps.widget.placepage.sections;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -14,6 +14,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import app.organicmaps.R;
|
||||
import app.organicmaps.bookmarks.data.MapObject;
|
||||
import app.organicmaps.bookmarks.data.Metadata;
|
||||
import app.organicmaps.widget.placepage.PlacePageViewModel;
|
||||
|
||||
public class PlacePagePhoneFragment extends Fragment implements Observer<MapObject>
|
||||
{
|
||||
|
@ -39,22 +40,23 @@ public class PlacePagePhoneFragment extends Fragment implements Observer<MapObje
|
|||
}
|
||||
|
||||
@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);
|
||||
![]()
```suggestion
if (mapObject != null)
mPhoneAdapter.refreshPhones(mapObject.getMetadata(Metadata.MetadataType.FMD_PHONE_NUMBER));
```
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged(MapObject mapObject)
|
||||
public void onChanged(@Nullable MapObject mapObject)
|
||||
{
|
||||
mPhoneAdapter.refreshPhones(mapObject.getMetadata(Metadata.MetadataType.FMD_PHONE_NUMBER));
|
||||
if (mapObject != null)
|
||||
mPhoneAdapter.refreshPhones(mapObject.getMetadata(Metadata.MetadataType.FMD_PHONE_NUMBER));
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package app.organicmaps.widget.placepage;
|
||||
package app.organicmaps.widget.placepage.sections;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
@ -19,6 +19,9 @@ import app.organicmaps.bookmarks.data.MapObject;
|
|||
import app.organicmaps.bookmarks.data.Metadata;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.util.UiUtils;
|
||||
import app.organicmaps.widget.placepage.PlaceDescriptionActivity;
|
||||
import app.organicmaps.widget.placepage.PlacePageUtils;
|
||||
import app.organicmaps.widget.placepage.PlacePageViewModel;
|
||||
|
||||
public class PlacePageWikipediaFragment extends Fragment implements Observer<MapObject>
|
||||
{
|
||||
|
@ -109,23 +112,26 @@ public class PlacePageWikipediaFragment extends Fragment implements Observer<Map
|
|||
}
|
||||
|
||||
@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)
|
||||
{
|
||||
mMapObject = mapObject;
|
||||
updateViews();
|
||||
if (mapObject != null)
|
||||
{
|
||||
mMapObject = mapObject;
|
||||
updateViews();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package app.organicmaps.widget.placepage;
|
||||
package app.organicmaps.widget.placepage.sections;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
|
@ -1,9 +1,10 @@
|
|||
package app.organicmaps.widget.placepage;
|
||||
package app.organicmaps.widget.placepage.sections;
|
||||
|
||||
import app.organicmaps.editor.data.HoursMinutes;
|
||||
import app.organicmaps.editor.data.Timespan;
|
||||
import app.organicmaps.editor.data.Timetable;
|
||||
import app.organicmaps.widget.placepage.PlaceOpeningHoursAdapter.WeekScheduleData;
|
||||
import app.organicmaps.widget.placepage.sections.PlaceOpeningHoursAdapter;
|
||||
import app.organicmaps.widget.placepage.sections.PlaceOpeningHoursAdapter.WeekScheduleData;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
Just curious, what is a MutableLiveData and why it is needed here?