Merge pull request #7580 from osmandapp/DownloadMap

Add "Download Map" Top Sheet card
This commit is contained in:
max-klaus 2019-10-01 12:41:26 +03:00 committed by GitHub
commit 5cae32057a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 707 additions and 166 deletions

View file

@ -707,6 +707,10 @@ public class OsmandRegions {
public BinaryMapDataObject getSmallestBinaryMapDataObjectAt(LatLon latLon) throws IOException {
List<BinaryMapDataObject> mapDataObjects = getBinaryMapDataObjectsAt(latLon);
return getSmallestBinaryMapDataObjectAt(mapDataObjects);
}
public BinaryMapDataObject getSmallestBinaryMapDataObjectAt(List<BinaryMapDataObject> mapDataObjects) throws IOException {
BinaryMapDataObject res = null;
double smallestArea = -1;
for (BinaryMapDataObject o : mapDataObjects) {

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="-100%p" android:toYDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="0" android:toYDelta="-100%p"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View file

@ -0,0 +1,13 @@
<?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_shadow_dialogtop_portrait" />
</item>
<item>
<shape>
<solid android:color="@color/list_background_color_dark" />
<corners android:bottomRightRadius="3dp"
android:bottomLeftRadius="3dp" />
</shape>
</item>
</layer-list>

View file

@ -0,0 +1,13 @@
<?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_shadow_dialogtop_portrait" />
</item>
<item>
<shape>
<solid android:color="@color/list_background_color_light" />
<corners android:bottomRightRadius="3dp"
android:bottomLeftRadius="3dp" />
</shape>
</item>
</layer-list>

View file

@ -0,0 +1,13 @@
<?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_shadow_dialogtop_landscape"/>
</item>
<item>
<shape>
<solid android:color="@color/list_background_color_dark"/>
<corners android:bottomRightRadius="3dp"
android:bottomLeftRadius="3dp" />
</shape>
</item>
</layer-list>

View file

@ -0,0 +1,13 @@
<?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_shadow_dialogtop_landscape"/>
</item>
<item>
<shape>
<solid android:color="@color/list_background_color_light"/>
<corners android:bottomRightRadius="3dp"
android:bottomLeftRadius="3dp" />
</shape>
</item>
</layer-list>

View file

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="@+id/touch_outside"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<FrameLayout
android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"/>
</android.support.design.widget.CoordinatorLayout>

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:background="?attr/list_background_color"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/list_content_padding"
android:layout_marginRight="@dimen/list_content_padding"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
osmand:typeface="@string/font_roboto_regular"
android:layout_marginTop="@dimen/list_content_padding"
android:layout_weight="1"
android:textSize="@dimen/default_list_text_size"
tools:text="@string/download_detaile_map" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/card_content_padding_large"
android:src="@drawable/img_download" />
</LinearLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/fileSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
osmand:typeface="@string/font_roboto_medium"
android:textColor="?attr/active_color_basic"
android:textSize="@dimen/default_desc_text_size"
tools:text="139mb" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/content_padding_small"
android:layout_marginBottom="@dimen/content_padding_small">
<include
android:id="@+id/btnClose"
layout="@layout/bottom_sheet_dialog_button" />
<View
android:id="@+id/buttons_divider"
android:layout_width="@dimen/content_padding"
android:layout_height="match_parent" />
<include
android:id="@+id/btnDownload"
layout="@layout/bottom_sheet_dialog_button" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -13,6 +13,8 @@
<dimen name="map_route_planning_land_width">510dp</dimen>
<dimen name="map_route_planning_land_width_minus_shadow">496dp</dimen>
<dimen name="card_content_padding_large">42dp</dimen>
<dimen name="map_address_height">60dp</dimen>
<dimen name="map_button_size">78dp</dimen>
<dimen name="map_small_button_size">66dp</dimen>

View file

@ -19,6 +19,8 @@
<dimen name="card_button_progress_size_small">24dp</dimen>
<dimen name="card_padding">12dp</dimen>
<dimen name="dlg_button_rect_rad">3dp</dimen>
<dimen name="card_content_padding_large">28dp</dimen>
<dimen name="widget_turn_lane_size">36dp</dimen>
<dimen name="widget_turn_lane_border">6dp</dimen>

View file

@ -14,6 +14,7 @@
<string name="shared_string_by_default">By default</string>
<string name="plugins_settings">Plugin settings</string>
<string name="logcat_buffer">Logcat buffer</string>
<string name="download_detaile_map">Download detailed %s map, to view this area.</string>
<string name="application_profile_changed">Application profile changed to \"%s\"</string>
<string name="switch_profile">Switch profile</string>
<string name="configure_profile">Configure profile</string>

View file

@ -647,6 +647,11 @@
<item name="android:windowExitAnimation">@anim/shrink_from_top</item>
</style>
<style name="Animations.PopUpMenu.Top">
<item name="android:windowEnterAnimation">@anim/slide_in_top</item>
<item name="android:windowExitAnimation">@anim/slide_out_top</item>
</style>
<style name="Animations.PopUpMenu.Bottom">
<item name="android:windowEnterAnimation">@anim/slide_in_bottom</item>
<item name="android:windowExitAnimation">@anim/slide_out_bottom</item>

View file

@ -500,7 +500,6 @@ public class AppInitializer implements IProgress {
app.travelDbHelper = startupInit(app.travelDbHelper, TravelDbHelper.class);
app.lockHelper = startupInit(new LockHelper(app), LockHelper.class);
initOpeningHoursParser();
}

View file

@ -133,7 +133,7 @@ public class MapActivityLayers {
mapVectorLayer = new MapVectorLayer(mapTileLayer, false);
mapView.addLayer(mapVectorLayer, 0.5f);
downloadedRegionsLayer = new DownloadedRegionsLayer();
downloadedRegionsLayer = new DownloadedRegionsLayer(activity);
mapView.addLayer(downloadedRegionsLayer, 0.5f);
// 0.9 gpx layer

View file

@ -1,102 +1,9 @@
package net.osmand.plus.base;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import net.osmand.plus.OnDialogFragmentResultListener;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
public abstract class BottomSheetDialogFragment extends DialogFragment {
private OnDialogFragmentResultListener dialogFragmentResultListener;
@NonNull
public abstract class BottomSheetDialogFragment extends OsmAndSheetDialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Context context = requireContext();
OsmandApplication app = (OsmandApplication) context.getApplicationContext();
OsmandSettings settings = app.getSettings();
int themeId = settings.isLightContent() ? R.style.OsmandLightTheme_BottomSheet : R.style.OsmandDarkTheme_BottomSheet;
BottomSheetDialog dialog = new BottomSheetDialog(context, themeId);
dialog.setCanceledOnTouchOutside(true);
Window window = dialog.getWindow();
if (!settings.DO_NOT_USE_ANIMATIONS.get() && window != null) {
window.getAttributes().windowAnimations = R.style.Animations_PopUpMenu_Bottom;
}
return dialog;
}
@Nullable
@Override
public abstract View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnDialogFragmentResultListener) {
dialogFragmentResultListener = (OnDialogFragmentResultListener) context;
}
}
@Override
public void onDetach() {
super.onDetach();
dialogFragmentResultListener = null;
}
@Nullable
public OnDialogFragmentResultListener getResultListener() {
return dialogFragmentResultListener;
}
@Nullable
protected OsmandApplication getMyApplication() {
Activity activity = getActivity();
if (activity != null) {
return (OsmandApplication) activity.getApplication();
} else {
return null;
}
}
@NonNull
protected OsmandApplication requiredMyApplication() {
return (OsmandApplication) requireActivity().getApplication();
}
@Nullable
protected Drawable getIcon(@DrawableRes int drawableRes, @ColorRes int color) {
OsmandApplication app = getMyApplication();
if (app != null) {
return app.getUIUtilities().getIcon(drawableRes, color);
} else {
return null;
}
}
@Nullable
protected Drawable getContentIcon(@DrawableRes int drawableRes) {
OsmandApplication app = getMyApplication();
if (app != null) {
return app.getUIUtilities().getThemedIcon(drawableRes);
} else {
return null;
}
protected SheetDialogType getSheetDialogType() {
return SheetDialogType.BOTTOM;
}
}

View file

@ -35,14 +35,10 @@ import java.util.List;
public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFragment {
private static final String USED_ON_MAP_KEY = "used_on_map";
private static final int DEFAULT_VALUE = -1;
protected List<BaseBottomSheetItem> items = new ArrayList<>();
protected boolean usedOnMap = true;
protected boolean nightMode;
protected int themeRes;
protected View dismissButton;
protected View rightButton;
@ -52,17 +48,9 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
@StringRes
protected int dismissButtonStringRes = R.string.shared_string_cancel;
public void setUsedOnMap(boolean usedOnMap) {
this.usedOnMap = usedOnMap;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
usedOnMap = savedInstanceState.getBoolean(USED_ON_MAP_KEY);
}
nightMode = isNightMode(requiredMyApplication());
themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
}
@ -113,26 +101,6 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
return mainView;
}
@Override
public void onStart() {
super.onStart();
FragmentActivity activity = requireActivity();
if (!AndroidUiHelper.isOrientationPortrait(activity)) {
final Window window = getDialog().getWindow();
if (window != null) {
WindowManager.LayoutParams params = window.getAttributes();
params.width = activity.getResources().getDimensionPixelSize(R.dimen.landscape_bottom_sheet_dialog_fragment_width);
window.setAttributes(params);
}
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(USED_ON_MAP_KEY, usedOnMap);
}
@Override
public void onDestroyView() {
super.onDestroyView();
@ -310,11 +278,4 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
protected int getLandscapeSidesBgResId() {
return nightMode ? R.drawable.bg_bottom_sheet_sides_landscape_dark : R.drawable.bg_bottom_sheet_sides_landscape_light;
}
private boolean isNightMode(@NonNull OsmandApplication app) {
if (usedOnMap) {
return app.getDaynightHelper().isNightModeForMapControls();
}
return !app.getSettings().isLightContent();
}
}

View file

@ -0,0 +1,166 @@
package net.osmand.plus.base;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import net.osmand.plus.OnDialogFragmentResultListener;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.helpers.AndroidUiHelper;
public abstract class OsmAndSheetDialogFragment extends DialogFragment {
private static final String USED_ON_MAP_KEY = "used_on_map";
private OnDialogFragmentResultListener dialogFragmentResultListener;
private int dialogWidth;
protected boolean usedOnMap = true;
protected boolean nightMode;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
usedOnMap = savedInstanceState.getBoolean(USED_ON_MAP_KEY);
}
dialogWidth = requireActivity().getResources().getDimensionPixelSize(R.dimen.landscape_bottom_sheet_dialog_fragment_width);
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Context context = requireContext();
OsmandApplication app = (OsmandApplication) context.getApplicationContext();
OsmandSettings settings = app.getSettings();
int themeId = settings.isLightContent() ? R.style.OsmandLightTheme_BottomSheet : R.style.OsmandDarkTheme_BottomSheet;
nightMode = isNightMode(app);
OsmandSheetDialog dialog = new OsmandSheetDialog(context, themeId, getSheetDialogType());
dialog.setCanceledOnTouchOutside(getCancelOnTouchOutside());
dialog.setInteractWithOutside(getInteractWithOutside());
Window window = dialog.getWindow();
if (window != null && !settings.DO_NOT_USE_ANIMATIONS.get()) {
window.getAttributes().windowAnimations = getSheetDialogType().getAnimationStyleResId();
}
return dialog;
}
@Nullable
@Override
public abstract View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnDialogFragmentResultListener) {
dialogFragmentResultListener = (OnDialogFragmentResultListener) context;
}
}
@Override
public void onDetach() {
super.onDetach();
dialogFragmentResultListener = null;
}
@Override
public void onStart() {
super.onStart();
final Window window = getDialog().getWindow();
FragmentActivity activity = requireActivity();
if (window != null) {
window.setDimAmount(getBackgroundDimAmount());
if (!AndroidUiHelper.isOrientationPortrait(activity)) {
View container = window.findViewById(OsmandSheetDialog.CONTAINER_ID);
if (container != null) {
container.getLayoutParams().width = dialogWidth;
}
}
}
}
@Nullable
public OnDialogFragmentResultListener getResultListener() {
return dialogFragmentResultListener;
}
@Nullable
protected OsmandApplication getMyApplication() {
Activity activity = getActivity();
if (activity != null) {
return (OsmandApplication) activity.getApplication();
} else {
return null;
}
}
@NonNull
protected OsmandApplication requiredMyApplication() {
return (OsmandApplication) requireActivity().getApplication();
}
@Nullable
protected Drawable getIcon(@DrawableRes int drawableRes, @ColorRes int color) {
OsmandApplication app = getMyApplication();
if (app != null) {
return app.getUIUtilities().getIcon(drawableRes, color);
} else {
return null;
}
}
@Nullable
protected Drawable getContentIcon(@DrawableRes int drawableRes) {
OsmandApplication app = getMyApplication();
if (app != null) {
return app.getUIUtilities().getThemedIcon(drawableRes);
} else {
return null;
}
}
public void setUsedOnMap(boolean usedOnMap) {
this.usedOnMap = usedOnMap;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(USED_ON_MAP_KEY, usedOnMap);
}
private boolean isNightMode(@NonNull OsmandApplication app) {
if (usedOnMap) {
return app.getDaynightHelper().isNightModeForMapControls();
}
return !app.getSettings().isLightContent();
}
protected abstract SheetDialogType getSheetDialogType();
protected boolean getCancelOnTouchOutside() {
return true;
}
protected boolean getInteractWithOutside() {
return false;
}
protected float getBackgroundDimAmount() {
return 0.3f;
}
}

View file

@ -1,5 +1,6 @@
package net.osmand.plus.base;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.res.TypedArray;
@ -7,31 +8,39 @@ import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import net.osmand.plus.R;
import static net.osmand.plus.base.SheetDialogType.*;
public class BottomSheetDialog extends Dialog {
public class OsmandSheetDialog extends Dialog {
public final static int CONTAINER_ID = 111111;
private boolean cancelable = true;
private boolean canceledOnTouchOutside = true;
private boolean interactWithOutside = false;
private boolean canceledOnTouchOutsideSet;
private SheetDialogType dialogType;
public BottomSheetDialog(@NonNull Context context) {
this(context, 0);
public OsmandSheetDialog(@NonNull Context context) {
this(context, 0, BOTTOM);
}
public BottomSheetDialog(@NonNull Context context, int themeResId) {
public OsmandSheetDialog(@NonNull Context context, int themeResId, SheetDialogType dialogType) {
super(context, themeResId);
this.dialogType = dialogType;
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
protected BottomSheetDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
protected OsmandSheetDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.cancelable = cancelable;
@ -80,11 +89,23 @@ public class BottomSheetDialog extends Dialog {
canceledOnTouchOutside = cancel;
canceledOnTouchOutsideSet = true;
}
public void setInteractWithOutside(boolean interactWithOutside) {
this.interactWithOutside = interactWithOutside;
}
@NonNull
private View wrapInContainer(int layoutResId, View view, LayoutParams params) {
final View res = View.inflate(getContext(), R.layout.bottom_sheet_dialog, null);
final FrameLayout container = (FrameLayout) res.findViewById(R.id.content_container);
final FrameLayout res = new FrameLayout(getContext());
final View touchOutside = new View(getContext());
final FrameLayout container = getContainer(dialogType);
ViewGroup.LayoutParams fullScreenParams = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
res.setLayoutParams(fullScreenParams);
touchOutside.setLayoutParams(fullScreenParams);
res.addView(touchOutside);
res.addView(container);
if (layoutResId != 0 && view == null) {
view = getLayoutInflater().inflate(layoutResId, container, false);
@ -95,7 +116,7 @@ public class BottomSheetDialog extends Dialog {
container.addView(view, params);
}
res.findViewById(R.id.touch_outside).setOnClickListener(new View.OnClickListener() {
touchOutside.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (cancelable && isShowing() && shouldWindowCloseOnTouchOutside()) {
@ -103,6 +124,19 @@ public class BottomSheetDialog extends Dialog {
}
}
});
touchOutside.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (interactWithOutside) {
Activity ownerActivity = getOwnerActivity();
if (ownerActivity != null) {
ownerActivity.dispatchTouchEvent(event);
}
}
return false;
}
});
container.setOnTouchListener(new View.OnTouchListener() {
@Override
@ -114,6 +148,29 @@ public class BottomSheetDialog extends Dialog {
return res;
}
private FrameLayout getContainer(SheetDialogType dialogType) {
if (dialogType == null) {
return null;
}
int width = LayoutParams.MATCH_PARENT;
int height = LayoutParams.WRAP_CONTENT;
int gravity = 0;
switch (dialogType) {
case TOP:
gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
break;
case BOTTOM:
gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
break;
}
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height);
params.gravity = gravity;
FrameLayout container = new FrameLayout(getContext());
container.setLayoutParams(params);
container.setId(CONTAINER_ID);
return container;
}
private boolean shouldWindowCloseOnTouchOutside() {
if (!canceledOnTouchOutsideSet) {

View file

@ -0,0 +1,19 @@
package net.osmand.plus.base;
import net.osmand.plus.R;
public enum SheetDialogType {
TOP(R.style.Animations_PopUpMenu_Top),
BOTTOM(R.style.Animations_PopUpMenu_Bottom);
SheetDialogType(int animationStyleResId) {
this.animationStyleResId = animationStyleResId;
}
private int animationStyleResId;
public int getAnimationStyleResId() {
return animationStyleResId;
}
}

View file

@ -0,0 +1,9 @@
package net.osmand.plus.base;
public abstract class TopSheetDialogFragment extends OsmAndSheetDialogFragment {
@Override
protected SheetDialogType getSheetDialogType() {
return SheetDialogType.TOP;
}
}

View file

@ -0,0 +1,178 @@
package net.osmand.plus.download.ui;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.SheetDialogType;
import net.osmand.plus.base.TopSheetDialogFragment;
import net.osmand.plus.download.DownloadValidationManager;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.widgets.style.CustomTypefaceSpan;
public class DownloadMapDialogFragment extends TopSheetDialogFragment {
public static final String TAG = "DownloadMapDialogFragment";
private final static String REGION_NAME = "REGION_NAME";
protected DownloadValidationManager downloadValidationManager;
private View btnClose;
private View btnDownload;
private TextView tvDescription;
private TextView tvSize;
private IndexItem currentIndexItem;
private String currentRegionName;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
readBundle(getArguments());
View mainView = View.inflate(new ContextThemeWrapper(getContext(), nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme), R.layout.card_download_detailed_map, null);
if (!AndroidUiHelper.isOrientationPortrait(requireActivity())) {
mainView.setBackgroundResource(getLandscapeBottomSidesBgResId());
} else {
mainView.setBackgroundResource(getPortraitBgResId());
}
downloadValidationManager = new DownloadValidationManager(getMyApplication());
tvDescription = mainView.findViewById(R.id.description);
tvSize = mainView.findViewById(R.id.fileSize);
btnClose = mainView.findViewById(R.id.btnClose);
btnDownload = mainView.findViewById(R.id.btnDownload);
UiUtilities.setupDialogButton(nightMode, btnClose, UiUtilities.DialogButtonType.SECONDARY, getString(R.string.shared_string_close));
UiUtilities.setupDialogButton(nightMode, btnDownload, UiUtilities.DialogButtonType.PRIMARY, getString(R.string.shared_string_download));
refreshView();
return mainView;
}
public void refreshData(final String newRegionName, final IndexItem newIndexItem) {
getMyApplication().runInUIThread(new Runnable() {
@Override
public void run() {
currentRegionName = newRegionName;
currentIndexItem = newIndexItem;
refreshView();
}
});
}
private void refreshView() {
if (currentRegionName != null) {
String descriptionText = String.format(getString(R.string.download_detaile_map), currentRegionName);
int startIndex = descriptionText.indexOf(currentRegionName);
int endIndex = startIndex + currentRegionName.length();
SpannableStringBuilder description = new SpannableStringBuilder(descriptionText);
Typeface typeface = FontCache.getRobotoMedium(getMyApplication());
description.setSpan(new CustomTypefaceSpan(typeface), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tvDescription.setText(description);
}
if (currentIndexItem != null) {
String size = currentIndexItem.getSizeDescription(getMyApplication()).toLowerCase();
tvSize.setText(size);
btnDownload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
downloadValidationManager.startDownload(getActivity(), currentIndexItem);
dismiss();
}
});
}
btnClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
}
protected void readBundle(Bundle bundle) {
if (bundle != null) {
currentRegionName = bundle.getString(REGION_NAME);
}
}
public static DownloadMapDialogFragment newInstance(FragmentManager fragmentManager, IndexItem indexItem, String name, boolean usedOnMap) {
Bundle bundle = new Bundle();
bundle.putString(REGION_NAME, name);
DownloadMapDialogFragment fragment = new DownloadMapDialogFragment();
fragment.setArguments(bundle);
fragment.setCurrentIndexItem(indexItem);
fragment.setUsedOnMap(usedOnMap);
return fragment;
}
public static void showInstance(FragmentManager fragmentManager, IndexItem indexItem, String name, boolean usedOnMap) {
DownloadMapDialogFragment fragment = newInstance(fragmentManager, indexItem, name, usedOnMap);
fragmentManager.beginTransaction()
.add(fragment, TAG).commitAllowingStateLoss();
}
public static void hideInstance(FragmentManager fragmentManager) {
DownloadMapDialogFragment fragment = (DownloadMapDialogFragment) fragmentManager.findFragmentByTag(TAG);
if (fragment != null) {
fragment.dismiss();
}
}
@Override
protected SheetDialogType getSheetDialogType() {
return SheetDialogType.TOP;
}
public void setCurrentIndexItem(IndexItem currentIndexItem) {
this.currentIndexItem = currentIndexItem;
}
@DrawableRes
protected int getPortraitBgResId() {
return nightMode ? R.drawable.bg_top_menu_dark : R.drawable.bg_top_menu_light;
}
@DrawableRes
protected int getLandscapeBottomSidesBgResId() {
return nightMode ? R.drawable.bg_top_sheet_bottom_sides_landscape_dark : R.drawable.bg_top_sheet_bottom_sides_landscape_light;
}
@Override
protected boolean getCancelOnTouchOutside() {
return false;
}
@Override
protected boolean getInteractWithOutside() {
return true;
}
@Override
protected float getBackgroundDimAmount() {
return 0;
}
}

View file

@ -0,0 +1,35 @@
package net.osmand.plus.download.ui;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.download.ui.DownloadMapDialogFragment;
public class DownloadMapDialogManager {
private IndexItem currentIndexItem;
public void showDialog(AppCompatActivity activity, IndexItem newIndexItem, String newRegionName, boolean usedOnMap) {
if (newIndexItem != null) {
if (!newIndexItem.equals(this.currentIndexItem)) {
currentIndexItem = newIndexItem;
FragmentManager fragmentManager = activity.getSupportFragmentManager();
DownloadMapDialogFragment dialogFragment =
(DownloadMapDialogFragment) fragmentManager.findFragmentByTag(DownloadMapDialogFragment.TAG);
if (dialogFragment != null) {
//refresh dialog data
dialogFragment.refreshData(newRegionName, newIndexItem);
} else {
//create a new dialog
DownloadMapDialogFragment.showInstance(activity.getSupportFragmentManager(), newIndexItem, newRegionName, usedOnMap);
}
}
}
}
public void hideDialog(AppCompatActivity activity) {
currentIndexItem = null;
DownloadMapDialogFragment.hideInstance(activity.getSupportFragmentManager());
}
}

View file

@ -22,11 +22,12 @@ import net.osmand.AndroidUtils;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.R;
import net.osmand.plus.base.BottomSheetDialogFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.widgets.tools.ExtendedBottomSheetBehavior;
import net.osmand.plus.widgets.tools.ExtendedBottomSheetBehavior.BottomSheetCallback;
public class AdditionalActionsBottomSheetDialogFragment extends net.osmand.plus.base.BottomSheetDialogFragment {
public class AdditionalActionsBottomSheetDialogFragment extends BottomSheetDialogFragment {
public static final String TAG = "AdditionalActionsBottomSheetDialogFragment";

View file

@ -8,6 +8,7 @@ import android.graphics.Paint.Join;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PointF;
import android.support.v7.app.AppCompatActivity;
import android.text.TextPaint;
import android.util.DisplayMetrics;
import android.view.WindowManager;
@ -26,6 +27,8 @@ import net.osmand.plus.activities.LocalIndexHelper;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.download.DownloadActivityType;
import net.osmand.plus.download.ui.DownloadMapDialogManager;
import net.osmand.plus.download.DownloadIndexesThread;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.mapcontextmenu.other.MapMultiSelectionMenu;
@ -51,6 +54,8 @@ public class DownloadedRegionsLayer extends OsmandMapLayer implements IContextMe
private OsmandApplication app;
private OsmandMapTileView view;
private MapActivity mapActivity;
private DownloadMapDialogManager downloadDialogManager;
private Paint paintDownloaded;
private Path pathDownloaded;
private Paint paintSelected;
@ -73,6 +78,13 @@ public class DownloadedRegionsLayer extends OsmandMapLayer implements IContextMe
private static int ZOOM_TO_SHOW_BORDERS = 7;
private static int ZOOM_TO_SHOW_SELECTION_ST = 3;
private static int ZOOM_TO_SHOW_SELECTION = 8;
private static int ZOOM_MIN_TO_SHOW_DOWNLOAD_DIALOG = 9;
private static int ZOOM_MAX_TO_SHOW_DOWNLOAD_DIALOG = 11;
public DownloadedRegionsLayer(MapActivity activity) {
this.mapActivity = activity;
this.downloadDialogManager = new DownloadMapDialogManager();
}
public static class DownloadMapObject {
private BinaryMapDataObject dataObject;
@ -180,6 +192,10 @@ public class DownloadedRegionsLayer extends OsmandMapLayer implements IContextMe
if(zoom < ZOOM_TO_SHOW_SELECTION_ST) {
return;
}
//make sure no maps are loaded for the location
checkMapToDownload(zoom, data.results);
// draw objects
if (osmandRegions.isInitialized() && zoom >= ZOOM_TO_SHOW_SELECTION_ST && zoom < ZOOM_TO_SHOW_SELECTION) {
final List<BinaryMapDataObject> currentObjects = new LinkedList<>();
@ -332,6 +348,61 @@ public class DownloadedRegionsLayer extends OsmandMapLayer implements IContextMe
return empty;
}
private void checkMapToDownload(int zoom, List<BinaryMapDataObject> currentObjects) {
boolean found = false;
if (zoom >= ZOOM_MIN_TO_SHOW_DOWNLOAD_DIALOG && zoom <= ZOOM_MAX_TO_SHOW_DOWNLOAD_DIALOG
&& currentObjects != null) {
IndexItem indexItem = null;
String name = null;
WorldRegion regionData = null;
int cx = view.getCurrentRotatedTileBox().getCenter31X();
int cy = view.getCurrentRotatedTileBox().getCenter31Y();
for (int i = 0; i < currentObjects.size(); i++) {
final BinaryMapDataObject o = currentObjects.get(i);
if (!osmandRegions.contain(o, cx, cy)) {
continue;
}
String fullName = osmandRegions.getFullName(o);
regionData = osmandRegions.getRegionData(fullName);
if (regionData != null && regionData.isRegionMapDownload()) {
String regionDownloadName = regionData.getRegionDownloadName();
if (regionDownloadName != null && checkIfObjectDownloaded(regionDownloadName)) {
downloadDialogManager.hideDialog(getActivity());
return;
}
}
}
BinaryMapDataObject smallestRegion = null;
try {
smallestRegion = app.getRegions().getSmallestBinaryMapDataObjectAt(currentObjects);
} catch (IOException e) {
downloadDialogManager.hideDialog(mapActivity);
}
String fullName = osmandRegions.getFullName(smallestRegion);
regionData = osmandRegions.getRegionData(fullName);
DownloadIndexesThread downloadThread = app.getDownloadThread();
List<IndexItem> indexItems = downloadThread.getIndexes().getIndexItems(regionData);
for (IndexItem item : indexItems) {
if (item.getType() == DownloadActivityType.NORMAL_FILE
&& !(item.isDownloaded() || downloadThread.isDownloading(item))) {
found = true;
indexItem = item;
name = regionData.getLocaleName();
break;
}
}
if (found) {
downloadDialogManager.showDialog(getActivity(), indexItem, name, true);
} else {
downloadDialogManager.hideDialog(getActivity());
}
} else {
downloadDialogManager.hideDialog(getActivity());
}
}
@Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings nightMode) {
if(view.getMainLayer() instanceof MapTileLayer) {
@ -556,5 +627,9 @@ public class DownloadedRegionsLayer extends OsmandMapLayer implements IContextMe
public void clearSelectedObject() {
selectedObjects = new LinkedList<>();
}
protected MapActivity getActivity() {
return mapActivity;
}
}