[android][refactoring] Made place page controller composite to make changing place page implementation in runtime possible

This commit is contained in:
Александр Зацепин 2020-02-14 19:13:12 +03:00 committed by yoksnod
parent 772311ba0e
commit e4a11fd75f
7 changed files with 261 additions and 51 deletions

View file

@ -124,7 +124,7 @@ import com.mapswithme.maps.widget.menu.BaseMenu;
import com.mapswithme.maps.widget.menu.MainMenu;
import com.mapswithme.maps.widget.menu.MyPositionButton;
import com.mapswithme.maps.widget.placepage.PlacePageController;
import com.mapswithme.maps.widget.placepage.PlacePageControllerFactory;
import com.mapswithme.maps.widget.placepage.PlacePageControllerComposite;
import com.mapswithme.maps.widget.placepage.RoutingModeListener;
import com.mapswithme.util.Counters;
import com.mapswithme.util.InputUtils;
@ -265,7 +265,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
private final OnClickListener mOnMyPositionClickListener = new CurrentPositionClickListener();
@SuppressWarnings("NullableProblems")
@NonNull
private PlacePageController mPlacePageController;
private PlacePageController<MapObject> mPlacePageController;
@Nullable
private Tutorial mTutorial;
@Nullable
@ -514,8 +514,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
setContentView(R.layout.activity_map);
mPlacePageController = PlacePageControllerFactory.createBottomSheetPlacePageController(this, this, this,
this);
mPlacePageController = new PlacePageControllerComposite(this, this, this, this);
mPlacePageController.initialize();
mPlacePageController.onActivityCreated(this, savedInstanceState);
@ -782,7 +782,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (mPlacePageController.isClosed())
return false;
mPlacePageController.close();
mPlacePageController.close(true);
return true;
}
@ -1026,7 +1026,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
@Override
public void toggleRouteSettings(@NonNull RoadType roadType)
{
mPlacePageController.close();
mPlacePageController.close(true);
RoutingOptions.addOption(roadType);
rebuildLastRouteInternal();
}
@ -1574,7 +1574,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
}
else
{
mPlacePageController.close();
mPlacePageController.close(true);
}
}

View file

@ -0,0 +1,6 @@
package com.mapswithme.maps.base;
public interface Supportable<T>
{
boolean support(T object);
}

View file

@ -133,9 +133,13 @@ public class BottomSheetPlacePageController implements PlacePageController<MapOb
private final AnchorBottomSheetBehavior.BottomSheetCallback mSheetCallback
= new DefaultBottomSheetCallback(mBottomSheetChangedListener);
private boolean mDeactivateMapSelection;
private void onHiddenInternal()
{
Framework.nativeDeactivatePopup();
if (mDeactivateMapSelection)
Framework.nativeDeactivatePopup();
mDeactivateMapSelection = false;
PlacePageUtils.moveViewportUp(mPlacePage, mViewportMinHeight);
UiUtils.invisible(mButtonsLayout);
mPlacePageTracker.onHidden();
@ -214,7 +218,7 @@ public class BottomSheetPlacePageController implements PlacePageController<MapOb
mToolbar = mActivity.findViewById(R.id.pp_toolbar);
UiUtils.extendViewWithStatusBar(mToolbar);
UiUtils.showHomeUpButton(mToolbar);
mToolbar.setNavigationOnClickListener(v -> close());
mToolbar.setNavigationOnClickListener(v -> close(true));
mPlacePage = mActivity.findViewById(R.id.placepage);
mPlacePageBehavior = AnchorBottomSheetBehavior.from(mPlacePage);
mPlacePageBehavior.addBottomSheetCallback(mSheetCallback);
@ -387,8 +391,9 @@ public class BottomSheetPlacePageController implements PlacePageController<MapOb
}
@Override
public void close()
public void close(boolean deactivateMapSelection)
{
mDeactivateMapSelection = deactivateMapSelection;
mPlacePageBehavior.setState(AnchorBottomSheetBehavior.STATE_HIDDEN);
mPlacePage.reset();
}
@ -457,7 +462,7 @@ public class BottomSheetPlacePageController implements PlacePageController<MapOb
if (!Framework.nativeHasPlacePageInfo())
{
close();
close(false);
return;
}
@ -560,7 +565,14 @@ public class BottomSheetPlacePageController implements PlacePageController<MapOb
@Override
public void closePlacePage()
{
close();
close(true);
}
@Override
public boolean support(MapObject object)
{
// TODO: only for tests.
return !object.getTitle().equals("Петровский Путевой Дворец");
}
private class PlacePageGestureListener extends GestureDetector.SimpleOnGestureListener

View file

@ -40,7 +40,10 @@ public class ElevationProfileBottomSheetController implements PlacePageControlle
@Override
public void onSheetDirectionIconChange()
{
// TODO: coming soon;
if (UiUtils.isLandscape(mActivity))
return;
PlacePageUtils.setPullDrawable(mSheetBehavior, mSheet, R.id.pull_icon);
}
@Override
@ -78,6 +81,8 @@ public class ElevationProfileBottomSheetController implements PlacePageControlle
private final AnchorBottomSheetBehavior.BottomSheetCallback mSheetCallback
= new DefaultBottomSheetCallback(mBottomSheetChangedListener);
private boolean mDeactivateMapSelection;
ElevationProfileBottomSheetController(@NonNull Activity activity,
@NonNull SlideListener slideListener)
{
@ -89,12 +94,16 @@ public class ElevationProfileBottomSheetController implements PlacePageControlle
public void openFor(@NonNull MapObject object)
{
mMapObject = object;
mSheetBehavior.setState(AnchorBottomSheetBehavior.STATE_COLLAPSED);
if (mSheetBehavior.getSkipCollapsed())
mSheetBehavior.setState(AnchorBottomSheetBehavior.STATE_EXPANDED);
else
mSheetBehavior.setState(AnchorBottomSheetBehavior.STATE_COLLAPSED);
}
@Override
public void close()
public void close(boolean deactivateMapSelection)
{
mDeactivateMapSelection = deactivateMapSelection;
mSheetBehavior.setState(AnchorBottomSheetBehavior.STATE_HIDDEN);
}
@ -154,10 +163,6 @@ public class ElevationProfileBottomSheetController implements PlacePageControlle
mViewPortMinWidth = mSheet.getResources().getDimensionPixelSize(R.dimen.viewport_min_width);
mSheetBehavior = AnchorBottomSheetBehavior.from(mSheet);
mSheetBehavior.addBottomSheetCallback(mSheetCallback);
mSheetBehavior.setPeekHeight(mSheet.getResources()
.getDimensionPixelSize(R.dimen.elevation_profile_peek_height));
if (UiUtils.isLandscape(mActivity))
mSheetBehavior.setSkipCollapsed(true);
}
@Override
@ -180,7 +185,7 @@ public class ElevationProfileBottomSheetController implements PlacePageControlle
if (!Framework.nativeHasPlacePageInfo())
{
close();
close(false);
return;
}
@ -189,19 +194,38 @@ public class ElevationProfileBottomSheetController implements PlacePageControlle
return;
mMapObject = object;
// TODO: probably the state should be restored as well.
if (UiUtils.isLandscape(mActivity))
{
// In case when bottom sheet was collapsed for vertical orientation then after rotation
// we should expand bottom sheet forcibly for horizontal orientation. It's by design.
if (!PlacePageUtils.isHiddenState(mSheetBehavior.getState()))
{
mSheetBehavior.setState(AnchorBottomSheetBehavior.STATE_EXPANDED);
}
return;
}
PlacePageUtils.setPullDrawable(mSheetBehavior, mSheet, R.id.pull_icon);
}
private void onHiddenInternal()
{
if (mDeactivateMapSelection)
Framework.nativeDeactivatePopup();
mDeactivateMapSelection = false;
if (UiUtils.isLandscape(mActivity))
{
PlacePageUtils.moveViewPortRight(mSheet, mViewPortMinWidth);
return;
}
Framework.nativeDeactivatePopup();
PlacePageUtils.moveViewportUp(mSheet, mViewportMinHeight);
}
@Override
public boolean support(MapObject object)
{
// TODO: only for tests.
return object.getTitle().equals("Петровский Путевой Дворец");
}
}

View file

@ -6,12 +6,14 @@ import android.os.Bundle;
import androidx.annotation.NonNull;
import com.mapswithme.maps.base.Initializable;
import com.mapswithme.maps.base.Savable;
import com.mapswithme.maps.base.Supportable;
public interface PlacePageController<T> extends Initializable, Savable<Bundle>,
Application.ActivityLifecycleCallbacks
Application.ActivityLifecycleCallbacks,
Supportable<T>
{
void openFor(@NonNull T object);
void close();
void close(boolean deactivateMapSelection);
boolean isClosed();
interface SlideListener

View file

@ -0,0 +1,193 @@
package com.mapswithme.maps.widget.placepage;
import android.app.Activity;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapswithme.maps.bookmarks.data.MapObject;
import com.mapswithme.maps.purchase.AdsRemovalPurchaseControllerProvider;
import java.util.ArrayList;
import java.util.List;
public class PlacePageControllerComposite implements PlacePageController<MapObject>
{
@NonNull
private final Activity mActivity;
@NonNull
private final AdsRemovalPurchaseControllerProvider mAdsProvider;
@NonNull
private final PlacePageController.SlideListener mSlideListener;
@Nullable
private final RoutingModeListener mRoutingModeListener;
@NonNull
private final List<PlacePageController<MapObject>> mControllers = new ArrayList<>();
@SuppressWarnings("NullableProblems")
@NonNull
private PlacePageController<MapObject> mActiveController;
public PlacePageControllerComposite(@NonNull Activity activity,
@NonNull AdsRemovalPurchaseControllerProvider adsProvider,
@NonNull SlideListener slideListener, @Nullable RoutingModeListener routingModeListener)
{
mActivity = activity;
mAdsProvider = adsProvider;
mSlideListener = slideListener;
mRoutingModeListener = routingModeListener;
}
@Override
public void openFor(@NonNull MapObject object)
{
boolean support = mActiveController.support(object);
if (support)
{
mActiveController.openFor(object);
return;
}
mActiveController.close(false);
PlacePageController<MapObject> controller = findControllerFor(object);
if (controller == null)
throw new UnsupportedOperationException("Map object '" + object + "' can't be opened " +
"by existing controllers");
mActiveController = controller;
mActiveController.openFor(object);
}
@Override
public void close(boolean deactivateMapSelection)
{
mActiveController.close(deactivateMapSelection);
}
@Override
public boolean isClosed()
{
return mActiveController.isClosed();
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState)
{
mActiveController.onActivityCreated(activity, savedInstanceState);
}
@Override
public void onActivityStarted(Activity activity)
{
mActiveController.onActivityStarted(activity);
}
@Override
public void onActivityResumed(Activity activity)
{
mActiveController.onActivityResumed(activity);
}
@Override
public void onActivityPaused(Activity activity)
{
mActiveController.onActivityPaused(activity);
}
@Override
public void onActivityStopped(Activity activity)
{
mActiveController.onActivityStopped(activity);
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState)
{
mActiveController.onActivitySaveInstanceState(activity, outState);
}
@Override
public void onActivityDestroyed(Activity activity)
{
mActiveController.onActivityDestroyed(activity);
}
@Override
public void initialize()
{
if (!mControllers.isEmpty())
throw new AssertionError("Place page controllers already initialized!");
PlacePageController<MapObject> poiPlacePageController =
createBottomSheetPlacePageController(mActivity, mAdsProvider, mSlideListener, mRoutingModeListener);
poiPlacePageController.initialize();
mControllers.add(poiPlacePageController);
PlacePageController<MapObject> elevationProfileController =
createElevationProfileBottomSheetController(mActivity, mSlideListener);
elevationProfileController.initialize();
mControllers.add(elevationProfileController);
mActiveController = poiPlacePageController;
}
@Override
public void destroy()
{
if (mControllers.isEmpty())
throw new AssertionError("Place page controllers already destroyed!");
mControllers.clear();
}
@Override
public void onSave(@NonNull Bundle outState)
{
mActiveController.onSave(outState);
}
@Override
public void onRestore(@NonNull Bundle inState)
{
MapObject object = inState.getParcelable(PlacePageUtils.EXTRA_MAP_OBJECT);
if (object != null)
{
PlacePageController<MapObject> controller = findControllerFor(object);
if (controller != null)
mActiveController = controller;
}
mActiveController.onRestore(inState);
}
@Nullable
private PlacePageController<MapObject> findControllerFor(@NonNull MapObject object)
{
for (PlacePageController<MapObject> controller : mControllers)
{
if (controller.support(object))
return controller;
}
return null;
}
@Override
public boolean support(MapObject object)
{
return mActiveController.support(object);
}
@NonNull
private static PlacePageController<MapObject> createBottomSheetPlacePageController(
@NonNull Activity activity, @NonNull AdsRemovalPurchaseControllerProvider provider,
@NonNull PlacePageController.SlideListener listener,
@Nullable RoutingModeListener routingModeListener)
{
return new BottomSheetPlacePageController(activity, provider, listener, routingModeListener);
}
@NonNull
private static PlacePageController<MapObject> createElevationProfileBottomSheetController(
@NonNull Activity activity, @NonNull PlacePageController.SlideListener listener)
{
return new ElevationProfileBottomSheetController(activity, listener);
}
}

View file

@ -1,27 +0,0 @@
package com.mapswithme.maps.widget.placepage;
import android.app.Activity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapswithme.maps.bookmarks.data.MapObject;
import com.mapswithme.maps.purchase.AdsRemovalPurchaseControllerProvider;
public class PlacePageControllerFactory
{
@NonNull
public static PlacePageController<MapObject> createBottomSheetPlacePageController(
@NonNull Activity activity, @NonNull AdsRemovalPurchaseControllerProvider provider,
@NonNull PlacePageController.SlideListener listener,
@Nullable RoutingModeListener routingModeListener)
{
return new BottomSheetPlacePageController(activity, provider, listener, routingModeListener);
}
@NonNull
public static PlacePageController<MapObject> createElevationProfileBottomSheetController(
@NonNull Activity activity, @NonNull PlacePageController.SlideListener listener)
{
return new ElevationProfileBottomSheetController(activity, listener);
}
}