android: move place page view fragment

Signed-off-by: Arnaud Vergnet <arnaud.vergnet@mailo.com>
This commit is contained in:
Arnaud Vergnet 2022-12-31 13:30:15 +01:00 committed by Viktor Govako
parent 7f62e38996
commit a176a548d1
12 changed files with 458 additions and 611 deletions

View file

@ -51,13 +51,18 @@
android:paddingBottom="@dimen/margin_base"
android:visibility="invisible" />
</RelativeLayout>
<app.organicmaps.widget.placepage.PlacePageView
<androidx.core.widget.NestedScrollViewClickFixed
android:id="@+id/placepage"
style="?attr/bottomSheetStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?attr/bottomSheetStyle"
android:fillViewport="true"
app:layout_behavior="@string/placepage_behavior" />
app:layout_behavior="@string/placepage_behavior" >
<androidx.fragment.app.FragmentContainerView
android:id="@+id/placepage_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.core.widget.NestedScrollViewClickFixed>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/pp_buttons_fragment"
android:layout_width="match_parent"

View file

@ -1,23 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<merge
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical">
<include
android:id="@+id/pp__preview"
layout="@layout/place_page_preview"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<include
android:id="@+id/pp__details_frame"
layout="@layout/place_page_details"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical">
<include
android:id="@+id/pp__preview"
layout="@layout/place_page_preview"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<include
android:id="@+id/pp__details_frame"
layout="@layout/place_page_details"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?panel"/>
</LinearLayout>
</merge>
android:background="?panel" />
</LinearLayout>

View file

@ -122,7 +122,6 @@
<dimen name="map_buttons_bottom_max_width">300dp</dimen>
<dimen name="appbar_elevation">4dp</dimen>
<dimen name="placepage_elevation">4dp</dimen>
<dimen name="tabs_height">64dp</dimen>

View file

@ -82,7 +82,7 @@ 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.RoutingModeListener;
import app.organicmaps.widget.placepage.PlacePageView;
import app.organicmaps.util.Config;
import app.organicmaps.util.Counters;
import app.organicmaps.util.SharingUtils;
@ -112,11 +112,11 @@ public class MwmActivity extends BaseMwmFragmentActivity
BookmarkManager.BookmarksLoadingListener,
FloatingSearchToolbarController.SearchToolbarListener,
PlacePageController.SlideListener,
RoutingModeListener,
NoConnectionListener,
MenuBottomSheetFragment.MenuBottomSheetInterfaceWithHeader,
ToggleMapLayerFragment.LayerItemClickListener,
PlacePageButtons.PlacePageButtonClickListener
PlacePageButtons.PlacePageButtonClickListener,
PlacePageView.PlacePageViewListener
{
private static final String TAG = MwmActivity.class.getSimpleName();
@ -909,14 +909,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
RoutingController.get().rebuildLastRoute();
}
@Override
public void toggleRouteSettings(@NonNull RoadType roadType)
{
closePlacePage();
RoutingOptions.addOption(roadType);
rebuildLastRouteInternal();
}
private void onIsolinesStateChanged(@NonNull IsolinesState type)
{
if (type != IsolinesState.EXPIREDDATA)
@ -1831,4 +1823,30 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
mPlacePageController.onPlacePageButtonClick(item);
}
@Override
public void onPlacePageHeightChange(int previewHeight)
{
mPlacePageController.onPlacePageHeightChange(previewHeight);
}
@Override
public void onPlacePageRequestClose()
{
mPlacePageController.onPlacePageRequestClose();
}
@Override
public void onPlacePageRequestToggleState()
{
mPlacePageController.onPlacePageRequestToggleState();
}
@Override
public void onPlacePageRequestToggleRouteSettings(@NonNull RoadType roadType)
{
closePlacePage();
RoutingOptions.addOption(roadType);
rebuildLastRouteInternal();
}
}

View file

@ -135,15 +135,15 @@ public class ElevationProfileViewRenderer implements PlacePageViewRenderer<Place
@Override
public void onSave(@NonNull Bundle outState)
{
outState.putParcelable(PlacePageUtils.EXTRA_PLACE_PAGE_DATA, mElevationInfo);
// outState.putParcelable(PlacePageUtils.EXTRA_PLACE_PAGE_DATA, mElevationInfo);
}
@Override
public void onRestore(@NonNull Bundle inState)
{
mElevationInfo = Utils.getParcelable(inState, PlacePageUtils.EXTRA_PLACE_PAGE_DATA, ElevationInfo.class);
if (mElevationInfo != null)
render(mElevationInfo);
// mElevationInfo = Utils.getParcelable(inState, PlacePageUtils.EXTRA_PLACE_PAGE_DATA, ElevationInfo.class);
// if (mElevationInfo != null)
// render(mElevationInfo);
}
@Override

View file

@ -29,7 +29,7 @@ public final class PlacePageButtons extends Fragment implements Observer<List<Pl
private PlacePageButtonClickListener mItemListener;
private ViewGroup mButtonsContainer;
private PlacePageButtonsViewModel viewModel;
private PlacePageViewModel viewModel;
@Nullable
@Override
@ -48,7 +48,7 @@ public final class PlacePageButtons extends Fragment implements Observer<List<Pl
return windowInsets;
});
mMaxButtons = getResources().getInteger(R.integer.pp_buttons_max);
viewModel = new ViewModelProvider(requireActivity()).get(PlacePageButtonsViewModel.class);
viewModel = new ViewModelProvider(requireActivity()).get(PlacePageViewModel.class);
viewModel.getCurrentButtons().observe(requireActivity(), this);
createButtons(viewModel.getCurrentButtons().getValue());
}

View file

@ -3,25 +3,24 @@ package app.organicmaps.widget.placepage;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.res.Resources;
import android.location.Location;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.GestureDetectorCompat;
import androidx.core.widget.NestedScrollViewClickFixed;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import app.organicmaps.Framework;
import app.organicmaps.MwmActivity;
import app.organicmaps.R;
import app.organicmaps.base.Initializable;
import app.organicmaps.base.Savable;
import app.organicmaps.bookmarks.data.MapObject;
import app.organicmaps.location.LocationHelper;
import app.organicmaps.location.LocationListener;
import app.organicmaps.settings.RoadType;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import app.organicmaps.util.log.Logger;
@ -33,28 +32,29 @@ import java.util.Objects;
public class PlacePageController implements Initializable<Activity>,
Savable<Bundle>,
LocationListener,
PlacePageView.OnPlacePageRequestCloseListener,
PlacePageView.PlacePageViewListener,
PlacePageButtons.PlacePageButtonClickListener,
MenuBottomSheetFragment.MenuBottomSheetInterface
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;
@Nullable
private final RoutingModeListener mRoutingModeListener;
@SuppressWarnings("NullableProblems")
@NonNull
private BottomSheetBehavior<View> mPlacePageBehavior;
@SuppressWarnings("NullableProblems")
private final BottomSheetBehavior<View> mPlacePageBehavior;
@NonNull
private PlacePageView mPlacePage;
private int mViewportMinHeight;
private final NestedScrollViewClickFixed mPlacePage;
private final int mViewportMinHeight;
private final AppCompatActivity mMwmActivity;
private final float mButtonsHeight;
private final int mMaxButtons;
private final PlacePageViewModel viewModel;
private int mPreviewHeight;
private boolean mDeactivateMapSelection = true;
private AppCompatActivity mMwmActivity;
private float mButtonsHeight;
@NonNull
private final BottomSheetChangedListener mBottomSheetChangedListener = new BottomSheetChangedListener()
{
@ -73,7 +73,6 @@ public class PlacePageController implements Initializable<Activity>,
@Override
public void onSheetCollapsed()
{
mPlacePage.resetScroll();
setPeekHeight();
}
@ -90,17 +89,31 @@ public class PlacePageController implements Initializable<Activity>,
PlacePageUtils.moveViewportUp(mPlacePage, mViewportMinHeight);
}
};
@NonNull
private final BottomSheetBehavior.BottomSheetCallback mSheetCallback
= new DefaultBottomSheetCallback(mBottomSheetChangedListener);
private int mMaxButtons;
private PlacePageButtonsViewModel viewModel;
public PlacePageController(@NonNull SlideListener listener,
@Nullable RoutingModeListener routingModeListener)
@SuppressLint("ClickableViewAccessibility")
public PlacePageController(@Nullable Activity activity,
@NonNull SlideListener listener)
{
mSlideListener = listener;
mRoutingModeListener = routingModeListener;
Objects.requireNonNull(activity);
mMwmActivity = (AppCompatActivity) activity;
Resources res = activity.getResources();
mViewportMinHeight = res.getDimensionPixelSize(R.dimen.viewport_min_height);
mPlacePage = activity.findViewById(R.id.placepage);
mPlacePageBehavior = BottomSheetBehavior.from(mPlacePage);
BottomSheetBehavior.BottomSheetCallback sheetCallback = new DefaultBottomSheetCallback(mBottomSheetChangedListener);
mPlacePageBehavior.addBottomSheetCallback(sheetCallback);
mPlacePageBehavior.setHideable(true);
mPlacePageBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
UiUtils.bringViewToFrontOf(activity.findViewById(R.id.pp_buttons_fragment), mPlacePage);
mPlacePage.requestApplyInsets();
mButtonsHeight = mMwmActivity.getResources().getDimension(R.dimen.place_page_buttons_height);
mMaxButtons = mMwmActivity.getResources().getInteger(R.integer.pp_buttons_max);
viewModel = new ViewModelProvider(mMwmActivity).get(PlacePageViewModel.class);
}
private void onHiddenInternal()
@ -109,46 +122,7 @@ public class PlacePageController implements Initializable<Activity>,
Framework.nativeDeactivatePopup();
mDeactivateMapSelection = true;
PlacePageUtils.moveViewportUp(mPlacePage, mViewportMinHeight);
Fragment f = mMwmActivity.getSupportFragmentManager().findFragmentByTag("PLACE_PAGE_BUTTONS");
if (f != null)
{
mMwmActivity.getSupportFragmentManager().beginTransaction()
.remove(f)
.commit();
}
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void initialize(@Nullable Activity activity)
{
Objects.requireNonNull(activity);
mMwmActivity = (AppCompatActivity) activity;
Resources res = activity.getResources();
mViewportMinHeight = res.getDimensionPixelSize(R.dimen.viewport_min_height);
mPlacePage = activity.findViewById(R.id.placepage);
mPlacePageBehavior = BottomSheetBehavior.from(mPlacePage);
mPlacePageBehavior.addBottomSheetCallback(mSheetCallback);
mPlacePageBehavior.setHideable(true);
mPlacePageBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
PlacePageGestureListener ppGestureListener = new PlacePageGestureListener(mPlacePageBehavior);
GestureDetectorCompat gestureDetector = new GestureDetectorCompat(activity, ppGestureListener);
mPlacePage.addPlacePageGestureListener(ppGestureListener);
mPlacePage.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event));
mPlacePage.setOnPlacePageRequestCloseListener(this);
mPlacePage.setRoutingModeListener(mRoutingModeListener);
mPlacePage.setOnPlacePageContentChangeListener(this::setPeekHeight);
UiUtils.bringViewToFrontOf(activity.findViewById(R.id.pp_buttons_fragment), mPlacePage);
LocationHelper.INSTANCE.addListener(this);
mPlacePage.requestApplyInsets();
mButtonsHeight = mMwmActivity.getResources().getDimension(R.dimen.place_page_buttons_height);
mMaxButtons = mMwmActivity.getResources().getInteger(R.integer.pp_buttons_max);
viewModel = new ViewModelProvider(mMwmActivity).get(PlacePageButtonsViewModel.class);
viewModel.setMapObject(null);
}
public int getPlacePageWidth()
@ -175,42 +149,11 @@ public class PlacePageController implements Initializable<Activity>,
return items;
}
@Override
public void destroy()
{
LocationHelper.INSTANCE.removeListener(this);
}
public void openFor(@NonNull PlacePageData data)
{
mDeactivateMapSelection = true;
MapObject object = (MapObject) data;
mPlacePage.setMapObject(object, (isSameObject) -> {
@BottomSheetBehavior.State
int state = mPlacePageBehavior.getState();
if (isSameObject && !PlacePageUtils.isHiddenState(state))
return;
mPlacePage.resetScroll();
if (object.getOpeningMode() == MapObject.OPENING_MODE_DETAILS)
{
mPlacePageBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
return;
}
if (mMwmActivity.getSupportFragmentManager().findFragmentByTag("PLACE_PAGE_BUTTONS") == null)
{
mMwmActivity.getSupportFragmentManager().beginTransaction()
.add(R.id.pp_buttons_fragment,
PlacePageButtons.class, null, "PLACE_PAGE_BUTTONS")
.commit();
}
mPlacePage.post(() -> {
setPeekHeight();
mPlacePageBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
});
});
MapObject mapObject = (MapObject) data;
viewModel.setMapObject(mapObject);
}
private void setPeekHeight()
@ -233,14 +176,12 @@ public class PlacePageController implements Initializable<Activity>,
private int calculatePeekHeight()
{
// Buttons layout padding is the navigation bar height.
// Bottom sheets are displayed above it so we need to remove it from the computed size
final int organicPeekHeight = (int) (mPlacePage.getPreviewHeight() + mButtonsHeight);
final MapObject object = mPlacePage.getMapObject();
if (object != null)
final int organicPeekHeight = (int) (mPreviewHeight + mButtonsHeight);
final MapObject mapObject = viewModel.getMapObject().getValue();
if (mapObject != null)
{
@MapObject.OpeningMode
int mode = object.getOpeningMode();
int mode = mapObject.getOpeningMode();
if (mode == MapObject.OPENING_MODE_PREVIEW_PLUS)
{
View parent = (View) mPlacePage.getParent();
@ -256,7 +197,6 @@ public class PlacePageController implements Initializable<Activity>,
{
mDeactivateMapSelection = deactivateMapSelection;
mPlacePageBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
mPlacePage.reset();
}
public boolean isClosed()
@ -264,27 +204,10 @@ public class PlacePageController implements Initializable<Activity>,
return PlacePageUtils.isHiddenState(mPlacePageBehavior.getState());
}
@Override
public void onLocationUpdated(@NonNull Location location)
{
mPlacePage.refreshLocation(location);
}
@Override
public void onCompassUpdated(double north)
{
@BottomSheetBehavior.State
int currentState = mPlacePageBehavior.getState();
if (PlacePageUtils.isHiddenState(currentState))
return;
mPlacePage.refreshAzimuth(north);
}
@Override
public void onSave(@NonNull Bundle outState)
{
outState.putParcelable(PlacePageUtils.EXTRA_PLACE_PAGE_DATA, mPlacePage.getMapObject());
// no op
}
@Override
@ -292,28 +215,15 @@ public class PlacePageController implements Initializable<Activity>,
{
if (mPlacePageBehavior.getState() == BottomSheetBehavior.STATE_HIDDEN)
return;
if (!Framework.nativeHasPlacePageInfo())
{
close(false);
return;
}
MapObject object = Utils.getParcelable(inState, PlacePageUtils.EXTRA_PLACE_PAGE_DATA, MapObject.class);
if (object == null)
return;
@BottomSheetBehavior.State
int state = mPlacePageBehavior.getState();
mPlacePage.setMapObject(object, (isSameObject) -> restorePlacePageState(state));
}
private void restorePlacePageState(@BottomSheetBehavior.State int state)
@Override
public void onPlacePageHeightChange(int previewHeight)
{
mPlacePage.post(() -> {
mPlacePageBehavior.setState(state);
setPeekHeight();
});
mPreviewHeight = previewHeight;
setPeekHeight();
}
@Override
@ -322,10 +232,100 @@ public class PlacePageController implements Initializable<Activity>,
close(true);
}
@Override
public void onPlacePageRequestToggleState()
{
@BottomSheetBehavior.State
int state = mPlacePageBehavior.getState();
if (PlacePageUtils.isCollapsedState(state))
mPlacePageBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
else if (PlacePageUtils.isExpandedState(state))
mPlacePageBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
@Override
public void onPlacePageRequestToggleRouteSettings(@NonNull RoadType roadType)
{
// no op
}
@Override
public void onPlacePageButtonClick(PlacePageButtons.ButtonType item)
{
mPlacePage.onPlacePageButtonClick(item);
@Nullable final PlacePageView placePageFragment = (PlacePageView) mMwmActivity.getSupportFragmentManager()
.findFragmentByTag(PLACE_PAGE_FRAGMENT_TAG);
if (placePageFragment != null)
placePageFragment.onPlacePageButtonClick(item);
}
private void onMapObjectChange(@Nullable MapObject mapObject)
{
if (mapObject == null)
{
Fragment placePageButtonsFragment = mMwmActivity.getSupportFragmentManager()
.findFragmentByTag(PLACE_PAGE_BUTTONS_FRAGMENT_TAG);
if (placePageButtonsFragment != null)
{
mMwmActivity.getSupportFragmentManager().beginTransaction()
.remove(placePageButtonsFragment)
.commit();
}
Fragment placePageFragment = mMwmActivity.getSupportFragmentManager()
.findFragmentByTag(PLACE_PAGE_FRAGMENT_TAG);
if (placePageFragment != null)
{
mMwmActivity.getSupportFragmentManager().beginTransaction()
.remove(placePageFragment)
.commit();
}
}
else
{
if (mapObject.getOpeningMode() == MapObject.OPENING_MODE_DETAILS)
{
mPlacePageBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
return;
}
if (mMwmActivity.getSupportFragmentManager()
.findFragmentByTag(PLACE_PAGE_FRAGMENT_TAG) == null)
{
mMwmActivity.getSupportFragmentManager().beginTransaction()
.add(R.id.placepage_fragment,
PlacePageView.class, null, PLACE_PAGE_FRAGMENT_TAG)
.commit();
}
if (mMwmActivity.getSupportFragmentManager()
.findFragmentByTag(PLACE_PAGE_BUTTONS_FRAGMENT_TAG) == null)
{
mMwmActivity.getSupportFragmentManager().beginTransaction()
.add(R.id.pp_buttons_fragment,
PlacePageButtons.class, null, PLACE_PAGE_BUTTONS_FRAGMENT_TAG)
.commit();
}
mPlacePage.post(() -> {
setPeekHeight();
mPlacePageBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
});
}
}
@Override
public void onChanged(MapObject mapObject)
{
onMapObjectChange(mapObject);
}
@Override
public void initialize(@Nullable Activity activity)
{
Objects.requireNonNull(activity);
viewModel.getMapObject().observe((MwmActivity) activity, this);
}
@Override
public void destroy()
{
viewModel.getMapObject().removeObserver(this);
}
public interface SlideListener

View file

@ -1,45 +0,0 @@
package app.organicmaps.widget.placepage;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
class PlacePageGestureListener extends GestureDetector.SimpleOnGestureListener
{
@NonNull
private final BottomSheetBehavior<View> mBottomSheetBehavior;
PlacePageGestureListener(@NonNull BottomSheetBehavior<View> bottomSheetBehavior)
{
mBottomSheetBehavior = bottomSheetBehavior;
}
@NonNull
BottomSheetBehavior<View> getBottomSheetBehavior()
{
return mBottomSheetBehavior;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e)
{
@BottomSheetBehavior.State
int state = mBottomSheetBehavior.getState();
if (PlacePageUtils.isCollapsedState(state))
{
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
return true;
}
if (PlacePageUtils.isExpandedState(state))
{
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
return true;
}
return false;
}
}

View file

@ -12,8 +12,6 @@ import app.organicmaps.R;
class PlacePageUtils
{
static final String EXTRA_PLACE_PAGE_DATA = "extra_place_page_data";
static void moveViewportUp(@NonNull View placePageView, int viewportMinHeight)
{
placePageView.post(() -> {

View file

@ -3,12 +3,14 @@ package app.organicmaps.widget.placepage;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import app.organicmaps.bookmarks.data.MapObject;
import java.util.List;
public class PlacePageButtonsViewModel extends ViewModel
public class PlacePageViewModel extends ViewModel
{
private final MutableLiveData<List<PlacePageButtons.ButtonType>> mCurrentButtons = new MutableLiveData<>();
private final MutableLiveData<MapObject> mMapObject = new MutableLiveData<>();
public LiveData<List<PlacePageButtons.ButtonType>> getCurrentButtons()
{
@ -19,4 +21,14 @@ public class PlacePageButtonsViewModel extends ViewModel
{
mCurrentButtons.setValue(buttons);
}
public MutableLiveData<MapObject> getMapObject()
{
return mMapObject;
}
public void setMapObject(MapObject mapObject)
{
mMapObject.setValue(mapObject);
}
}

View file

@ -1,10 +0,0 @@
package app.organicmaps.widget.placepage;
import androidx.annotation.NonNull;
import app.organicmaps.settings.RoadType;
public interface RoutingModeListener
{
void toggleRouteSettings(@NonNull RoadType roadType);
}