Add ChooseRouteFragment with route cards

This commit is contained in:
Chumva 2018-12-19 17:46:00 +02:00
parent c876910188
commit dff9f3e588
9 changed files with 452 additions and 54 deletions

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<nine-patch android:src="@drawable/bg_card_shadow"/>
</item>
<item>
<shape>
<solid android:color="@color/bg_color_light"/>
<corners android:radius="4dp" />
</shape>
</item>
</layer-list>

View file

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_transparent">
<ImageButton
android:id="@+id/back_button"
android:layout_width="@dimen/map_button_size"
android:layout_height="@dimen/map_button_size"
android:layout_gravity="start"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginTop="@dimen/map_button_spacing"
android:background="@drawable/btn_circle"
android:contentDescription="@string/shared_string_collapse"
android:scaleType="center"
tools:src="@drawable/ic_action_test_light" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="vertical"
tools:visibility="visible">
<LinearLayout
android:id="@+id/fab_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="@dimen/map_button_margin"
android:layout_marginRight="@dimen/map_button_margin">
<ImageButton
android:id="@+id/map_my_location_button"
android:layout_width="@dimen/map_button_size"
android:layout_height="@dimen/map_button_size"
android:layout_gravity="bottom"
android:background="@drawable/btn_circle"
android:contentDescription="@string/shared_string_my_location"
tools:src="@drawable/ic_action_test_light" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginLeft="@dimen/map_button_spacing"
android:orientation="vertical">
<ImageButton
android:id="@+id/map_zoom_in_button"
android:layout_width="@dimen/map_button_size"
android:layout_height="@dimen/map_button_size"
android:background="@drawable/btn_circle"
android:contentDescription="@string/zoomIn"
tools:src="@drawable/ic_action_test_light" />
<ImageButton
android:id="@+id/map_zoom_out_button"
android:layout_width="@dimen/map_button_size"
android:layout_height="@dimen/map_button_size"
android:layout_marginTop="@dimen/map_button_spacing"
android:background="@drawable/btn_circle"
android:contentDescription="@string/zoomOut"
tools:src="@drawable/ic_action_test_light" />
</LinearLayout>
</LinearLayout>
<net.osmand.plus.LockableViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="bottom"
android:layout_marginTop="@dimen/content_padding" />
</LinearLayout>
</FrameLayout>

View file

@ -28,19 +28,13 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/route_info_buttons_padding_top_bottom"
android:paddingRight="@dimen/route_info_buttons_padding_top_bottom">
<LinearLayout
android:id="@+id/info_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingRight="@dimen/route_info_buttons_padding_top_bottom"
android:paddingTop="@dimen/content_padding">
<net.osmand.plus.routepreparationmenu.FlowLayout
android:id="@+id/routes_badges"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp" />
<LinearLayout
@ -69,8 +63,6 @@
</LinearLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/details_button"
android:layout_width="match_parent"

View file

@ -0,0 +1,297 @@
package net.osmand.plus.routepreparationmenu;
import android.Manifest;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.PagerAdapter;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import net.osmand.AndroidUtils;
import net.osmand.Location;
import net.osmand.plus.LockableViewPager;
import net.osmand.plus.OsmAndLocationProvider;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.routeCards.PublicTransportCard;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.router.TransportRoutePlanner;
import java.util.ArrayList;
import java.util.List;
public class ChooseRouteFragment extends BaseOsmAndFragment {
public static final String TAG = "ChooseRouteFragment";
private OsmandMapTileView map;
private MapActivity mapActivity;
private ImageButton myLocButtonView;
private boolean portrait;
private boolean nightMode;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mapActivity = (MapActivity) getActivity();
nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls();
portrait = AndroidUiHelper.isOrientationPortrait(mapActivity);
map = getMapActivity().getMapView();
View view = inflater.inflate(R.layout.fragment_show_all_routes, null);
AndroidUtils.addStatusBarPadding21v(mapActivity, view);
LockableViewPager viewPager = view.findViewById(R.id.pager);
List<PublicTransportCard> routeCards = new ArrayList<>();
List<TransportRoutePlanner.TransportRouteResult> routes = getMyApplication().getTransportRoutingHelper().getRoutes();
for (int i = 0; i < routes.size(); i++) {
PublicTransportCard card = new PublicTransportCard(mapActivity, nightMode, routes.get(i), i);
card.setShowTopShadow(false);
card.setShowBottomShadow(false);
routeCards.add(card);
}
viewPager.setClipToPadding(false);
ViewsPagerAdapter pagerAdapter = new ViewsPagerAdapter(mapActivity, routeCards);
viewPager.setAdapter(pagerAdapter);
viewPager.setSwipeLocked(routeCards.size() < 2);
if (!portrait) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtils.dpToPx(getMyApplication(), 200f));
params.gravity = Gravity.BOTTOM;
viewPager.setLayoutParams(params);
}
ImageButton backButtonView = (ImageButton) view.findViewById(R.id.back_button);
backButtonView.setImageDrawable(getContentIcon(R.drawable.ic_arrow_back));
AndroidUtils.setBackground(mapActivity, backButtonView, nightMode, R.drawable.btn_circle_trans, R.drawable.btn_circle_night);
backButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss(mapActivity);
}
});
View fabButtonsView = view.findViewById(R.id.fab_container);
ImageButton zoomInButtonView = (ImageButton) view.findViewById(R.id.map_zoom_in_button);
ImageButton zoomOutButtonView = (ImageButton) view.findViewById(R.id.map_zoom_out_button);
myLocButtonView = (ImageButton) view.findViewById(R.id.map_my_location_button);
if (portrait) {
updateImageButton(zoomInButtonView, R.drawable.map_zoom_in, R.drawable.map_zoom_in_night,
R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode);
updateImageButton(zoomOutButtonView, R.drawable.map_zoom_out, R.drawable.map_zoom_out_night,
R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode);
zoomInButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doZoomIn();
}
});
zoomOutButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doZoomOut();
}
});
myLocButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) {
mapActivity.getMapViewTrackingUtilities().backToLocationImpl();
} else {
ActivityCompat.requestPermissions(mapActivity,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
OsmAndLocationProvider.REQUEST_LOCATION_PERMISSION);
}
}
});
fabButtonsView.setVisibility(View.VISIBLE);
} else {
fabButtonsView.setVisibility(View.GONE);
}
updateMyLocation(mapActivity.getRoutingHelper());
return view;
}
@Override
public void onResume() {
super.onResume();
getMapActivity().getMapLayers().getMapControlsLayer().showMapControlsIfHidden();
MapRouteInfoMenu.chooseRoutesVisible = true;
}
public void onPause() {
super.onPause();
MapRouteInfoMenu.chooseRoutesVisible = false;
}
@Override
public int getStatusBarColorId() {
return R.color.status_bar_transparent_gradient;
}
private void updateMyLocation(RoutingHelper rh) {
Location lastKnownLocation = mapActivity.getMyApplication().getLocationProvider().getLastKnownLocation();
boolean enabled = lastKnownLocation != null;
boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation();
if (!enabled) {
myLocButtonView.setImageResource(R.drawable.map_my_location);
AndroidUtils.setBackground(mapActivity, myLocButtonView, nightMode, R.drawable.btn_circle_trans, R.drawable.btn_circle_night);
myLocButtonView.setContentDescription(mapActivity.getString(R.string.unknown_location));
} else if (tracked) {
myLocButtonView.setImageDrawable(getIcon(R.drawable.map_my_location, R.color.color_myloc_distance));
AndroidUtils.setBackground(mapActivity, myLocButtonView, nightMode, R.drawable.btn_circle_trans, R.drawable.btn_circle_night);
} else {
myLocButtonView.setImageResource(R.drawable.map_my_location);
AndroidUtils.setBackground(mapActivity, myLocButtonView, nightMode, R.drawable.btn_circle_blue, R.drawable.btn_circle_blue);
myLocButtonView.setContentDescription(mapActivity.getString(R.string.map_widget_back_to_loc));
}
if (mapActivity.getMyApplication().accessibilityEnabled()) {
myLocButtonView.setClickable(enabled && !tracked && rh.isFollowingMode());
}
}
private MapActivity getMapActivity() {
return (MapActivity) getActivity();
}
public void doZoomIn() {
if (map.isZooming() && map.hasCustomMapRatio()) {
getMapActivity().changeZoom(2, System.currentTimeMillis());
} else {
if (!map.hasCustomMapRatio()) {
//setCustomMapRatio();
}
getMapActivity().changeZoom(1, System.currentTimeMillis());
}
}
public void doZoomOut() {
if (!map.hasCustomMapRatio()) {
//setCustomMapRatio();
}
getMapActivity().changeZoom(-1, System.currentTimeMillis());
}
private void updateImageButton(ImageButton button, int iconLightId, int iconDarkId, int bgLightId, int bgDarkId, boolean night) {
button.setImageDrawable(getMapActivity().getMyApplication().getUIUtilities().getIcon(night ? iconDarkId : iconLightId));
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
button.setBackground(getMapActivity().getResources().getDrawable(night ? bgDarkId : bgLightId,
getMapActivity().getTheme()));
} else {
button.setBackgroundDrawable(getMapActivity().getResources().getDrawable(night ? bgDarkId : bgLightId));
}
}
@Override
protected Drawable getContentIcon(@DrawableRes int id) {
return getIcon(id, nightMode ? R.color.ctx_menu_info_text_dark : R.color.icon_color);
}
private void dismiss(MapActivity mapActivity) {
try {
mapActivity.getSupportFragmentManager().beginTransaction().remove(this).commitAllowingStateLoss();
} catch (Exception e) {
// ignore
}
}
public static boolean showInstance(FragmentManager fragmentManager) {
return showFragment(new ChooseRouteFragment(), fragmentManager);
}
private static boolean showFragment(ChooseRouteFragment fragment, FragmentManager fragmentManager) {
try {
fragment.setRetainInstance(true);
fragmentManager.beginTransaction()
.add(R.id.fragmentContainer, fragment, ChooseRouteFragment.TAG)
.commitAllowingStateLoss();
return true;
} catch (Exception e) {
return false;
}
}
private class ViewsPagerAdapter extends PagerAdapter {
private List<PublicTransportCard> cards;
private MapActivity mapActivity;
ViewsPagerAdapter(MapActivity mapActivity, List<PublicTransportCard> cards) {
this.mapActivity = mapActivity;
this.cards = cards;
}
@Override
public float getPageWidth(int position) {
return portrait ? super.getPageWidth(position) : 0.7f;
}
public void setCards(List<PublicTransportCard> cards) {
this.cards = cards;
notifyDataSetChanged();
}
@Override
public int getCount() {
return itemsCount();
}
private int itemsCount() {
return cards.size();
}
private View createPageView(int position) {
return cards.get(position).createCardView();
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, final int position) {
View view = createPageView(position);
view.setBackgroundDrawable(null);
view.setBackgroundResource(R.drawable.route_cards_topsides_light);
view.findViewById(R.id.details_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mapActivity.getMyApplication().getTransportRoutingHelper().setCurrentRoute(cards.get(position).getRouteId());
mapActivity.getMapView().refreshMap(true);
}
});
container.addView(view, 0);
return view;
}
@Override
public void destroyItem(@NonNull ViewGroup collection, int position, @NonNull Object view) {
collection.removeView((View) view);
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
}
}

View file

@ -92,6 +92,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener {
public static int directionInfo = -1;
private static boolean visible;
public static boolean controlVisible = false;
public static boolean chooseRoutesVisible = false;
public static final String TARGET_SELECT = "TARGET_SELECT";
private final RoutingHelper routingHelper;
@ -249,7 +250,6 @@ public class MapRouteInfoMenu implements IRouteInformationListener {
}
}
public int getCurrentMenuState() {
return currentMenuState;
}
@ -364,9 +364,8 @@ public class MapRouteInfoMenu implements IRouteInformationListener {
List<TransportRoutePlanner.TransportRouteResult> routes = transportHelper.getRoutes();
for (int i = 0; i < routes.size(); i++) {
PublicTransportCard card = new PublicTransportCard(mapActivity, nightMode, routes.get(i), i);
if (i == routes.size() - 1) {
card.setLastItem(true);
}
card.setShowBottomShadow(i == routes.size() - 1);
card.setShowTopShadow(i != 0);
routeCards.add(card);
}
LinearLayout cardsContainer = (LinearLayout) mainView.findViewById(R.id.route_menu_cards_container);

View file

@ -14,7 +14,8 @@ public abstract class BaseRouteCard {
protected OsmandApplication app;
protected boolean isLastItem;
boolean showTopShadow;
boolean showBottomShadow;
protected boolean nightMode;
public BaseRouteCard(OsmandApplication app, boolean nightMode) {
@ -46,7 +47,12 @@ public abstract class BaseRouteCard {
protected Drawable getColoredIcon(@DrawableRes int icon, @ColorRes int color) {
return app.getUIUtilities().getIcon(icon, color);
}
public void setLastItem(boolean lastItem) {
isLastItem = lastItem;
public void setShowTopShadow(boolean showTopShadow) {
this.showTopShadow = showTopShadow;
}
public void setShowBottomShadow(boolean showBottomShadow) {
this.showBottomShadow = showBottomShadow;
}
}

View file

@ -22,7 +22,7 @@ import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.routepreparationmenu.FlowLayout;
import net.osmand.plus.routing.TransportRoutingHelper;
import net.osmand.plus.routepreparationmenu.ChooseRouteFragment;
import net.osmand.plus.transport.TransportStopRoute;
import net.osmand.plus.transport.TransportStopType;
import net.osmand.plus.widgets.style.CustomTypefaceSpan;
@ -38,7 +38,6 @@ public class PublicTransportCard extends BaseRouteCard {
private MapActivity mapActivity;
private TransportRouteResult routeResult;
private TransportRoutingHelper transportHelper;
private View view;
@ -46,7 +45,6 @@ public class PublicTransportCard extends BaseRouteCard {
public PublicTransportCard(MapActivity mapActivity, boolean nightMode, TransportRouteResult routeResult, int routeId) {
super(mapActivity.getMyApplication(), nightMode);
this.transportHelper = app.getTransportRoutingHelper();
this.mapActivity = mapActivity;
this.routeResult = routeResult;
this.routeId = routeId;
@ -69,17 +67,22 @@ public class PublicTransportCard extends BaseRouteCard {
view.findViewById(R.id.details_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
transportHelper.setCurrentRoute(routeId);
mapActivity.getMapLayers().getMapControlsLayer().getMapRouteInfoMenu().hide();
ChooseRouteFragment.showInstance(mapActivity.getSupportFragmentManager());
}
});
view.findViewById(R.id.bottom_shadow).setVisibility(isLastItem ? View.VISIBLE : View.GONE);
view.findViewById(R.id.card_divider).setVisibility(routeId != 0 ? View.VISIBLE : View.GONE);
view.findViewById(R.id.bottom_shadow).setVisibility(showBottomShadow ? View.VISIBLE : View.GONE);
view.findViewById(R.id.card_divider).setVisibility(showTopShadow ? View.VISIBLE : View.GONE);
applyDayNightMode();
return view;
}
public int getRouteId() {
return routeId;
}
protected void applyDayNightMode() {
TextView fromLine = (TextView) view.findViewById(R.id.from_line);
TextView wayLine = (TextView) view.findViewById(R.id.way_line);

View file

@ -51,9 +51,9 @@ import net.osmand.plus.activities.MapActivity.ShowQuickSearchMode;
import net.osmand.plus.dashboard.DashboardOnMap.DashboardType;
import net.osmand.plus.dialogs.DirectionsDialogs;
import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu;
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu;
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.views.corenative.NativeCoreContext;
@ -767,7 +767,7 @@ public class MapControlsLayer extends OsmandMapLayer {
((app.accessibilityEnabled() || (System.currentTimeMillis() - touchEvent < TIMEOUT_TO_SHOW_BUTTONS)) && routeFollowingMode);
updateMyLocation(rh, routeDialogOpened || trackDialogOpened || contextMenuOpened);
boolean showButtons = (showRouteCalculationControls || !routeFollowingMode)
&& !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode() && !isInPlanRouteMode() && !contextMenuOpened;
&& !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode() && !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode();
//routePlanningBtn.setIconResId(routeFollowingMode ? R.drawable.ic_action_gabout_dark : R.drawable.map_directions);
if (rh.isFollowingMode()) {
routePlanningBtn.setIconResId(R.drawable.map_start_navigation);
@ -782,10 +782,10 @@ public class MapControlsLayer extends OsmandMapLayer {
routePlanningBtn.updateVisibility(showButtons);
menuControl.updateVisibility(showButtons);
mapZoomIn.updateVisibility(!routeDialogOpened && !contextMenuOpened);
mapZoomOut.updateVisibility(!routeDialogOpened && !contextMenuOpened);
mapZoomIn.updateVisibility(!routeDialogOpened && !contextMenuOpened && !isInChoosingRoutesMode());
mapZoomOut.updateVisibility(!routeDialogOpened && !contextMenuOpened && !isInChoosingRoutesMode());
boolean forceHideCompass = routeDialogOpened || trackDialogOpened
|| isInMeasurementToolMode() || isInPlanRouteMode() || contextMenuOpened;
|| isInMeasurementToolMode() || isInPlanRouteMode() || contextMenuOpened || isInChoosingRoutesMode();
compassHud.forceHideCompass = forceHideCompass;
compassHud.updateVisibility(!forceHideCompass && shouldShowCompass());
@ -793,9 +793,9 @@ public class MapControlsLayer extends OsmandMapLayer {
layersHud.update(app, isNight);
}
layersHud.updateVisibility(!routeDialogOpened && !trackDialogOpened && !isInMeasurementToolMode() && !isInPlanRouteMode()
&& !contextMenuOpened);
&& !contextMenuOpened && !isInChoosingRoutesMode());
quickSearchHud.updateVisibility(!routeDialogOpened && !trackDialogOpened && !isInMeasurementToolMode() && !isInPlanRouteMode()
&& !contextMenuOpened);
&& !contextMenuOpened && !isInChoosingRoutesMode());
if (!routePlanningMode && !routeFollowingMode) {
if (mapView.isZooming()) {
@ -875,7 +875,7 @@ public class MapControlsLayer extends OsmandMapLayer {
backToLocationControl.iv.setContentDescription(mapActivity.getString(R.string.map_widget_back_to_loc));
}
boolean visible = !(tracked && rh.isFollowingMode());
backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode());
backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode() && !isInChoosingRoutesMode());
if (app.accessibilityEnabled()) {
backToLocationControl.iv.setClickable(enabled && visible);
}
@ -1205,6 +1205,11 @@ public class MapControlsLayer extends OsmandMapLayer {
return mapActivity.getMapLayers().getMapMarkersLayer().isInPlanRouteMode();
}
private boolean isInChoosingRoutesMode() {
RoutingHelper rh = mapActivity.getRoutingHelper();
return rh.isPublicTransportMode() && rh.getTransportRoutingHelper().getRoutes() != null && MapRouteInfoMenu.chooseRoutesVisible;
}
public static View.OnLongClickListener getOnClickMagnifierListener(final OsmandMapTileView view) {
return new View.OnLongClickListener() {

View file

@ -1182,6 +1182,8 @@ public class RouteInfoWidgetsFactory {
visible = false;
} else if (!orientationPortrait && ma.getRoutingHelper().isRoutePlanningMode()) {
visible = false;
} else if (ma.getRoutingHelper().isPublicTransportMode() && ma.getRoutingHelper().getTransportRoutingHelper().getRoutes() != null) {
visible = !MapRouteInfoMenu.chooseRoutesVisible;
} else if (!tb.isZoomAnimated() && (tb.getZoom() != cacheRulerZoom || Math.abs(tb.getCenterTileX() - cacheRulerTileX) > 1 || Math
.abs(tb.getCenterTileY() - cacheRulerTileY) > 1 || mapDensity.get() != cacheMapDensity) &&
tb.getPixWidth() > 0 && maxWidth > 0) {