add ability to edit RouteLineDrawInfo and finish dialog UI

This commit is contained in:
nazar-kutz 2021-03-21 14:44:53 +02:00
parent 32e0defac0
commit 14bd85a64c
7 changed files with 1091 additions and 14 deletions

View file

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:text="@string/shared_string_color"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/color_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="Orange" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding_half"
android:paddingLeft="@dimen/content_padding_half"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
tools:itemCount="2"
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/point_editor_group_select_item"
tools:orientation="horizontal" />
</LinearLayout>
<FrameLayout
android:id="@+id/theme_toggle_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/content_padding_small" >
<include layout="@layout/custom_radio_buttons" />
</FrameLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Specify color for map mode: day." />
<FrameLayout
android:id="@+id/colors_card_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingRight="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"/>
</LinearLayout>

View file

@ -0,0 +1,170 @@
<?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:orientation="vertical">
<View
android:id="@+id/top_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/divider_color_basic"
android:focusable="false" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:text="@string/select_track_width"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/width_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="21" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="@dimen/context_menu_padding_margin_tiny">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding_half"
android:paddingLeft="@dimen/content_padding_half"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
tools:itemCount="3"
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/point_editor_group_select_item"
tools:orientation="horizontal" />
</LinearLayout>
<LinearLayout
android:id="@+id/slider_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/content_padding"
android:paddingBottom="@dimen/favorites_select_group_button_height">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:text="@string/shared_string_custom"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/width_value_tv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
tools:text="1" />
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/width_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:stepSize="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/width_value_min"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
tools:text="1" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/width_value_max"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
tools:text="24" />
</LinearLayout>
</LinearLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Route line would be use width specified on selected map style: OsmAnd." />
</LinearLayout>

View file

@ -0,0 +1,347 @@
package net.osmand.plus.routing.cards;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.AndroidUtils;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.ColorDialogs;
import net.osmand.plus.helpers.enums.DayNightMode;
import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
import net.osmand.plus.routing.RouteLineDrawInfo;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.ListStringPreference;
import net.osmand.plus.track.AppearanceViewHolder;
import net.osmand.plus.track.ColorsCard;
import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener;
import net.osmand.plus.widgets.MultiStateToggleButton;
import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import net.osmand.render.RenderingRulesStorage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class RouteLineColorCard extends BaseCard implements CardListener, ColorPickerListener {
private static final int DAY_TITLE_ID = R.string.day;
private static final int NIGHT_TITLE_ID = R.string.night;
private final Fragment targetFragment;
private ApplicationMode appMode;
private ColorsCard colorsCard;
private ColorTypeAdapter colorAdapter;
private RecyclerView groupRecyclerView;
private TextView tvColorName;
private TextView tvDescription;
private View themeToggleContainer;
private ViewGroup cardsContainer;
private ColorMode selectedMode;
private RouteLineDrawInfo routeLineDrawInfo;
private DayNightMode initMapTheme;
private DayNightMode selectedMapTheme;
private enum ColorMode {
DEFAULT(R.string.map_widget_renderer, R.drawable.ic_action_map_style),
CUSTOM(R.string.shared_string_custom, R.drawable.ic_action_settings);
ColorMode(int titleId, int iconId) {
this.titleId = titleId;
this.iconId = iconId;
}
int titleId;
int iconId;
}
public RouteLineColorCard(@NonNull MapActivity mapActivity,
@NonNull Fragment targetFragment,
@NonNull RouteLineDrawInfo routeLineDrawInfo,
@NonNull ApplicationMode appMode,
@NonNull DayNightMode initMapTheme,
@NonNull DayNightMode selectedMapTheme) {
super(mapActivity);
this.targetFragment = targetFragment;
this.routeLineDrawInfo = routeLineDrawInfo;
this.appMode = appMode;
this.initMapTheme = initMapTheme;
this.selectedMapTheme = selectedMapTheme;
}
@Override
public int getCardLayoutId() {
return R.layout.route_line_color_card;
}
@Override
protected void updateContent() {
tvColorName = view.findViewById(R.id.color_name);
tvDescription = view.findViewById(R.id.description);
colorAdapter = new ColorTypeAdapter();
groupRecyclerView = view.findViewById(R.id.recycler_view);
groupRecyclerView.setAdapter(colorAdapter);
groupRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
themeToggleContainer = view.findViewById(R.id.theme_toggle_container);
LinearLayout radioGroup = (LinearLayout) view.findViewById(R.id.custom_radio_buttons);
setupRadioGroup(radioGroup);
cardsContainer = (ViewGroup) view.findViewById(R.id.colors_card_container);
createColorSelector(cardsContainer);
initSelectedMode();
}
private void initSelectedMode() {
selectedMode = routeLineDrawInfo.getColor() == null ? ColorMode.DEFAULT : ColorMode.CUSTOM;
modeChanged();
}
private void modeChanged() {
if (selectedMode == ColorMode.DEFAULT) {
themeToggleContainer.setVisibility(View.GONE);
cardsContainer.setVisibility(View.GONE);
changeMapTheme(initMapTheme);
} else {
themeToggleContainer.setVisibility(View.VISIBLE);
cardsContainer.setVisibility(View.VISIBLE);
changeMapTheme(isNightMap() ? DayNightMode.NIGHT : DayNightMode.DAY);
}
updateSelectedColor();
updateDescription();
}
private void setupRadioGroup(LinearLayout buttonsContainer) {
RadioItem day = createMapThemeButton(false);
RadioItem night = createMapThemeButton(true);
MultiStateToggleButton radioGroup = new MultiStateToggleButton(app, buttonsContainer, nightMode);
radioGroup.setItems(day, night);
radioGroup.setSelectedItem(!isNightMap() ? day : night);
}
private RadioItem createMapThemeButton(final boolean isNight) {
RadioItem item = new RadioItem(app.getString(!isNight ? DAY_TITLE_ID : NIGHT_TITLE_ID));
item.setOnClickListener(new OnRadioItemClickListener() {
@Override
public boolean onRadioItemClick(RadioItem radioItem, View view) {
selectedMapTheme = isNight ? DayNightMode.NIGHT : DayNightMode.DAY;
changeMapTheme(selectedMapTheme);
updateDescription();
return true;
}
});
return item;
}
private void changeMapTheme(DayNightMode mapTheme) {
if (targetFragment instanceof OnMapThemeUpdateListener) {
((OnMapThemeUpdateListener) targetFragment).onMapThemeUpdated(mapTheme);
}
}
private void createColorSelector(ViewGroup container) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
List<Integer> colors = new ArrayList<>();
for (int color : ColorDialogs.pallette) {
colors.add(color);
}
Integer selectedColor = routeLineDrawInfo.getColor();
if (selectedColor != null) {
if (!ColorDialogs.isPaletteColor(selectedColor)) {
colors.add(selectedColor);
}
} else {
selectedColor = colors.get(0);
}
ListStringPreference preference = app.getSettings().CUSTOM_ROUTE_LINE_COLORS;
colorsCard = new ColorsCard(mapActivity, selectedColor, targetFragment, colors, preference, appMode);
colorsCard.setListener(this);
container.addView(colorsCard.build(mapActivity));
}
}
@Override
public void onColorSelected(Integer prevColor, int newColor) {
colorsCard.onColorSelected(prevColor, newColor);
updateSelectedColor();
}
private void updateSelectedColor() {
Integer color = selectedMode == ColorMode.CUSTOM ? colorsCard.getSelectedColor() : null;
routeLineDrawInfo.setColor(color);
updateColorName();
if (targetFragment instanceof OnSelectedColorChangeListener) {
((OnSelectedColorChangeListener) targetFragment).onSelectedColorChanged();
}
}
private void updateColorName() {
if (selectedMode == ColorMode.DEFAULT) {
tvColorName.setText(app.getString(R.string.map_widget_renderer));
} else {
int selectedColor = routeLineDrawInfo.getColor();
int colorNameId = ColorDialogs.getColorName(selectedColor);
tvColorName.setText(app.getString(colorNameId));
}
}
private void updateDescription() {
String description;
if (selectedMode == ColorMode.DEFAULT) {
String pattern = app.getString(R.string.route_line_use_map_style_appearance);
String color = app.getString(R.string.shared_string_color).toLowerCase();
description = String.format(pattern, color, getMapStyleName());
} else {
String pattern = app.getString(R.string.specify_color_for_map_mode);
String mapModeTitle = app.getString(isNightMap() ? NIGHT_TITLE_ID : DAY_TITLE_ID);
description = String.format(pattern, mapModeTitle.toLowerCase());
}
tvDescription.setText(description);
}
private String getMapStyleName() {
RendererRegistry rr = app.getRendererRegistry();
RenderingRulesStorage storage = rr.getCurrentSelectedRenderer();
if (storage == null) {
return "";
}
return RendererRegistry.getRendererName(app, storage.getName());
}
private boolean isNightMap() {
return selectedMapTheme.isNight();
}
@Override
public void onCardLayoutNeeded(@NonNull BaseCard card) {
}
@Override
public void onCardPressed(@NonNull BaseCard card) {
if (card instanceof ColorsCard) {
updateSelectedColor();
}
}
@Override
public void onCardButtonPressed(@NonNull BaseCard card, int buttonIndex) {
}
private class ColorTypeAdapter extends RecyclerView.Adapter<AppearanceViewHolder> {
private List<ColorMode> items = Arrays.asList(ColorMode.values());
@NonNull
@Override
public AppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode);
View view = themedInflater.inflate(R.layout.point_editor_group_select_item, parent, false);
view.getLayoutParams().width = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_width);
view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height);
AppearanceViewHolder holder = new AppearanceViewHolder(view);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AndroidUtils.setBackground(app, holder.button, nightMode, R.drawable.ripple_solid_light_6dp,
R.drawable.ripple_solid_dark_6dp);
}
return holder;
}
@Override
public void onBindViewHolder(@NonNull final AppearanceViewHolder holder, int position) {
ColorMode item = items.get(position);
holder.title.setText(app.getString(item.titleId));
updateButtonBg(holder, item);
updateTextAndIconColor(holder, item);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
selectedMode = items.get(holder.getAdapterPosition());
notifyItemRangeChanged(0, getItemCount());
modeChanged();
CardListener listener = getListener();
if (listener != null) {
listener.onCardPressed(RouteLineColorCard.this);
}
}
});
}
private void updateButtonBg(AppearanceViewHolder holder, ColorMode item) {
GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
if (rectContourDrawable != null) {
if (selectedMode == item) {
int strokeColor = ContextCompat.getColor(app, nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light);
rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 2), strokeColor);
} else {
int strokeColor = ContextCompat.getColor(app, nightMode ?
R.color.stroked_buttons_and_links_outline_dark :
R.color.stroked_buttons_and_links_outline_light);
rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 1), strokeColor);
}
holder.button.setImageDrawable(rectContourDrawable);
}
}
private void updateTextAndIconColor(AppearanceViewHolder holder, ColorMode item) {
Context ctx = holder.itemView.getContext();
int iconColorId;
int textColorId;
if (selectedMode == item) {
iconColorId = AndroidUtils.getColorFromAttr(ctx, R.attr.default_icon_color);
textColorId = AndroidUtils.getColorFromAttr(ctx, android.R.attr.textColor);
} else {
iconColorId = AndroidUtils.getColorFromAttr(ctx, R.attr.colorPrimary);
textColorId = iconColorId;
}
holder.icon.setImageDrawable(app.getUIUtilities().getPaintedIcon(item.iconId, iconColorId));
holder.title.setTextColor(textColorId);
}
@Override
public int getItemCount() {
return items.size();
}
}
public interface OnSelectedColorChangeListener {
void onSelectedColorChanged();
}
public interface OnMapThemeUpdateListener {
void onMapThemeUpdated(@NonNull DayNightMode mapTheme);
}
}

View file

@ -0,0 +1,313 @@
package net.osmand.plus.routing.cards;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.github.ksoichiro.android.observablescrollview.ScrollUtils;
import com.google.android.material.slider.Slider;
import net.osmand.AndroidUtils;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.routing.RouteLineDrawInfo;
import net.osmand.plus.routing.RouteLineHelper;
import net.osmand.plus.track.AppearanceViewHolder;
import net.osmand.plus.track.TrackAppearanceFragment.OnNeedScrollListener;
import net.osmand.render.RenderingRulesStorage;
import java.util.Arrays;
import java.util.List;
public class RouteLineWidthCard extends BaseCard {
private final static int CUSTOM_WIDTH_MIN = 1;
private final static int CUSTOM_WIDTH_MAX = 24;
private RouteLineDrawInfo routeLineDrawInfo;
private OnNeedScrollListener onNeedScrollListener;
private WidthMode selectedMode;
private WidthAdapter widthAdapter;
private View sliderContainer;
private RecyclerView groupRecyclerView;
private TextView tvModeType;
private TextView tvDescription;
private enum WidthMode {
DEFAULT(R.string.map_widget_renderer, R.drawable.ic_action_map_style, null),
THIN(R.string.rendering_value_thin_name, R.drawable.ic_action_track_line_thin_color, 5),
MEDIUM(R.string.rendering_value_medium_name, R.drawable.ic_action_track_line_medium_color, 13),
THICK(R.string.rendering_value_bold_name, R.drawable.ic_action_track_line_bold_color, 28),
CUSTOM(R.string.shared_string_custom, R.drawable.ic_action_settings, null);
WidthMode(int titleId, int iconId, Integer width) {
this.titleId = titleId;
this.iconId = iconId;
this.width = width;
}
int titleId;
int iconId;
Integer width;
}
public RouteLineWidthCard(@NonNull MapActivity mapActivity,
@NonNull RouteLineDrawInfo routeLineDrawInfo,
@NonNull OnNeedScrollListener onNeedScrollListener) {
super(mapActivity);
this.routeLineDrawInfo = routeLineDrawInfo;
this.onNeedScrollListener = onNeedScrollListener;
}
@Override
public int getCardLayoutId() {
return R.layout.route_line_width_card;
}
@Override
protected void updateContent() {
widthAdapter = new WidthAdapter();
groupRecyclerView = view.findViewById(R.id.recycler_view);
groupRecyclerView.setAdapter(widthAdapter);
groupRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
tvModeType = view.findViewById(R.id.width_type);
tvDescription = view.findViewById(R.id.description);
sliderContainer = view.findViewById(R.id.slider_container);
AndroidUiHelper.updateVisibility(view.findViewById(R.id.top_divider), isShowDivider());
initSelectedMode();
}
private void initSelectedMode() {
selectedMode = findAppropriateMode(getRouteLineWidth());
modeChanged();
}
private void modeChanged() {
updateHeader();
updateDescription();
updateCustomWidthSlider();
scrollMenuToSelectedItem();
}
public void updateItems() {
if (widthAdapter != null) {
widthAdapter.notifyDataSetChanged();
}
}
private void setRouteLineWidth(Integer width) {
routeLineDrawInfo.setWidth(width);
mapActivity.refreshMap();
}
private Integer getRouteLineWidth() {
return routeLineDrawInfo.getWidth();
}
private void updateHeader() {
tvModeType.setText(app.getString(selectedMode.titleId));
}
private void updateDescription() {
if (selectedMode == WidthMode.DEFAULT) {
String pattern = app.getString(R.string.route_line_use_map_style_appearance);
String width = app.getString(R.string.shared_string_color).toLowerCase();
String description = String.format(pattern, width, getMapStyleName());
tvDescription.setText(description);
tvDescription.setVisibility(View.VISIBLE);
} else {
tvDescription.setVisibility(View.GONE);
}
}
private String getMapStyleName() {
RendererRegistry rr = app.getRendererRegistry();
RenderingRulesStorage storage = rr.getCurrentSelectedRenderer();
if (storage == null) {
return "";
}
return RendererRegistry.getRendererName(app, storage.getName());
}
private void updateCustomWidthSlider() {
if (selectedMode == WidthMode.CUSTOM) {
Slider widthSlider = view.findViewById(R.id.width_slider);
widthSlider.setValueTo(CUSTOM_WIDTH_MAX);
widthSlider.setValueFrom(CUSTOM_WIDTH_MIN);
((TextView) view.findViewById(R.id.width_value_min)).setText(String.valueOf(CUSTOM_WIDTH_MIN));
((TextView) view.findViewById(R.id.width_value_max)).setText(String.valueOf(CUSTOM_WIDTH_MAX));
Integer width = getRouteLineWidth();
if (width == null || width > CUSTOM_WIDTH_MAX || width < CUSTOM_WIDTH_MIN) {
width = CUSTOM_WIDTH_MIN;
}
widthSlider.setValue(width);
final TextView tvCustomWidth = view.findViewById(R.id.width_value_tv);
widthSlider.addOnChangeListener(new Slider.OnChangeListener() {
@Override
public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
if (fromUser) {
Integer newWidth = (int) value;
setRouteLineWidth(newWidth);
tvCustomWidth.setText(String.valueOf(newWidth));
}
}
});
UiUtilities.setupSlider(widthSlider, nightMode, null, true);
ScrollUtils.addOnGlobalLayoutListener(sliderContainer, new Runnable() {
@Override
public void run() {
if (sliderContainer.getVisibility() == View.VISIBLE) {
onNeedScrollListener.onVerticalScrollNeeded(sliderContainer.getBottom());
}
}
});
AndroidUiHelper.updateVisibility(sliderContainer, true);
} else {
AndroidUiHelper.updateVisibility(sliderContainer, false);
}
}
private void scrollMenuToSelectedItem() {
int position = widthAdapter.getItemPosition(selectedMode);
if (position != -1) {
groupRecyclerView.scrollToPosition(position);
}
}
private static WidthMode findAppropriateMode(Integer width) {
WidthMode result = null;
if (width != null) {
for (WidthMode mode : WidthMode.values()) {
if (mode.width != null && (int) width == mode.width) {
result = mode;
break;
}
}
if (result == null) {
result = WidthMode.CUSTOM;
}
} else {
result = WidthMode.DEFAULT;
}
return result;
}
private class WidthAdapter extends RecyclerView.Adapter<AppearanceViewHolder> {
private final List<WidthMode> items = Arrays.asList(WidthMode.values());
@NonNull
@Override
public AppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode);
View view = themedInflater.inflate(R.layout.point_editor_group_select_item, parent, false);
view.getLayoutParams().width = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_width);
view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height);
AppearanceViewHolder holder = new AppearanceViewHolder(view);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AndroidUtils.setBackground(app, holder.button, nightMode, R.drawable.ripple_solid_light_6dp,
R.drawable.ripple_solid_dark_6dp);
}
return holder;
}
@Override
public void onBindViewHolder(@NonNull final AppearanceViewHolder holder, int position) {
WidthMode item = items.get(position);
holder.title.setText(app.getString(item.titleId));
updateButtonBg(holder, item);
updateTextAndIconColor(holder, item);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int prevSelectedPosition = getItemPosition(selectedMode);
selectedMode = items.get(holder.getAdapterPosition());
notifyItemChanged(holder.getAdapterPosition());
notifyItemChanged(prevSelectedPosition);
if (selectedMode != WidthMode.CUSTOM) {
setRouteLineWidth(selectedMode.width);
}
modeChanged();
CardListener listener = getListener();
if (listener != null) {
listener.onCardPressed(RouteLineWidthCard.this);
}
}
});
}
private void updateTextAndIconColor(AppearanceViewHolder holder, WidthMode item) {
Context ctx = holder.itemView.getContext();
int iconColor;
int textColorId;
if (selectedMode == item) {
iconColor = getIconColor(item, AndroidUtils.getColorFromAttr(ctx, R.attr.default_icon_color));
textColorId = AndroidUtils.getColorFromAttr(ctx, android.R.attr.textColor);
} else {
iconColor = getIconColor(item, AndroidUtils.getColorFromAttr(ctx, R.attr.colorPrimary));
textColorId = AndroidUtils.getColorFromAttr(ctx, R.attr.colorPrimary);
}
holder.icon.setImageDrawable(app.getUIUtilities().getPaintedIcon(item.iconId, iconColor));
holder.title.setTextColor(textColorId);
}
private int getIconColor(@NonNull WidthMode mode, @ColorInt int defaultColor) {
return mode.width != null ? RouteLineHelper.getColor(routeLineDrawInfo) : defaultColor;
}
private void updateButtonBg(AppearanceViewHolder holder, WidthMode item) {
GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
if (rectContourDrawable != null) {
if (selectedMode == item) {
int strokeColor = ContextCompat.getColor(app, nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light);
rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 2), strokeColor);
} else {
int strokeColor = ContextCompat.getColor(app, nightMode ?
R.color.stroked_buttons_and_links_outline_dark
: R.color.stroked_buttons_and_links_outline_light);
rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 1), strokeColor);
}
holder.button.setImageDrawable(rectContourDrawable);
}
}
@Override
public int getItemCount() {
return items.size();
}
int getItemPosition(WidthMode widthMode) {
return items.indexOf(widthMode);
}
}
}

View file

@ -54,10 +54,13 @@ import net.osmand.plus.profiles.SelectProfileBottomSheet.DialogMode;
import net.osmand.plus.profiles.SelectProfileBottomSheet.OnSelectProfileCallback; import net.osmand.plus.profiles.SelectProfileBottomSheet.OnSelectProfileCallback;
import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener; import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
import net.osmand.plus.routing.RouteLineDrawInfo;
import net.osmand.plus.routing.RouteLineHelper;
import net.osmand.plus.routing.RouteService; import net.osmand.plus.routing.RouteService;
import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem; import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
import net.osmand.plus.settings.backend.backup.SettingsHelper; import net.osmand.plus.settings.backend.backup.SettingsHelper;
import net.osmand.plus.settings.fragments.RouteLineAppearanceFragment.OnApplyRouteLineListener;
import net.osmand.plus.track.ColorsCard; import net.osmand.plus.track.ColorsCard;
import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener; import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener;
import net.osmand.plus.widgets.FlowLayout; import net.osmand.plus.widgets.FlowLayout;
@ -76,7 +79,7 @@ import static net.osmand.plus.profiles.SelectProfileBottomSheet.PROFILES_LIST_UP
import static net.osmand.plus.profiles.SelectProfileBottomSheet.PROFILE_KEY_ARG; import static net.osmand.plus.profiles.SelectProfileBottomSheet.PROFILE_KEY_ARG;
import static net.osmand.plus.routing.TransportRoutingHelper.PUBLIC_TRANSPORT_KEY; import static net.osmand.plus.routing.TransportRoutingHelper.PUBLIC_TRANSPORT_KEY;
public class ProfileAppearanceFragment extends BaseSettingsFragment implements OnSelectProfileCallback, CardListener, ColorPickerListener { public class ProfileAppearanceFragment extends BaseSettingsFragment implements OnSelectProfileCallback, CardListener, ColorPickerListener, OnApplyRouteLineListener {
private static final Log LOG = PlatformUtil.getLog(ProfileAppearanceFragment.class); private static final Log LOG = PlatformUtil.getLog(ProfileAppearanceFragment.class);
@ -161,6 +164,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
changedProfile.routeService = profile.routeService; changedProfile.routeService = profile.routeService;
changedProfile.locationIcon = profile.locationIcon; changedProfile.locationIcon = profile.locationIcon;
changedProfile.navigationIcon = profile.navigationIcon; changedProfile.navigationIcon = profile.navigationIcon;
changedProfile.routeLineDrawInfo = profile.routeLineDrawInfo;
isNewProfile = ApplicationMode.valueOfStringKey(changedProfile.stringKey, null) == null; isNewProfile = ApplicationMode.valueOfStringKey(changedProfile.stringKey, null) == null;
} }
requireMyActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { requireMyActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@ -181,6 +185,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
profile.routeService = baseModeForNewProfile.getRouteService(); profile.routeService = baseModeForNewProfile.getRouteService();
profile.locationIcon = baseModeForNewProfile.getLocationIcon(); profile.locationIcon = baseModeForNewProfile.getLocationIcon();
profile.navigationIcon = baseModeForNewProfile.getNavigationIcon(); profile.navigationIcon = baseModeForNewProfile.getNavigationIcon();
profile.routeLineDrawInfo = RouteLineHelper.createDrawInfoForAppMode(app, profile.parent);
} }
@Override @Override
@ -323,6 +328,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
outState.putBoolean(IS_BASE_PROFILE_IMPORTED, isBaseProfileImported); outState.putBoolean(IS_BASE_PROFILE_IMPORTED, isBaseProfileImported);
outState.putSerializable(PROFILE_LOCATION_ICON_KEY, changedProfile.locationIcon); outState.putSerializable(PROFILE_LOCATION_ICON_KEY, changedProfile.locationIcon);
outState.putSerializable(PROFILE_NAVIGATION_ICON_KEY, changedProfile.navigationIcon); outState.putSerializable(PROFILE_NAVIGATION_ICON_KEY, changedProfile.navigationIcon);
changedProfile.routeLineDrawInfo.saveToBundle(outState);
} }
private void restoreState(Bundle savedInstanceState) { private void restoreState(Bundle savedInstanceState) {
@ -336,6 +342,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
isBaseProfileImported = savedInstanceState.getBoolean(IS_BASE_PROFILE_IMPORTED); isBaseProfileImported = savedInstanceState.getBoolean(IS_BASE_PROFILE_IMPORTED);
changedProfile.locationIcon = (LocationIcon) savedInstanceState.getSerializable(PROFILE_LOCATION_ICON_KEY); changedProfile.locationIcon = (LocationIcon) savedInstanceState.getSerializable(PROFILE_LOCATION_ICON_KEY);
changedProfile.navigationIcon = (NavigationIcon) savedInstanceState.getSerializable(PROFILE_NAVIGATION_ICON_KEY); changedProfile.navigationIcon = (NavigationIcon) savedInstanceState.getSerializable(PROFILE_NAVIGATION_ICON_KEY);
changedProfile.routeLineDrawInfo = new RouteLineDrawInfo(savedInstanceState);
isNewProfile = savedInstanceState.getBoolean(IS_NEW_PROFILE_KEY); isNewProfile = savedInstanceState.getBoolean(IS_NEW_PROFILE_KEY);
} }
@ -771,6 +778,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
mode.setCustomIconColor(changedProfile.customColor); mode.setCustomIconColor(changedProfile.customColor);
mode.setLocationIcon(changedProfile.locationIcon); mode.setLocationIcon(changedProfile.locationIcon);
mode.setNavigationIcon(changedProfile.navigationIcon); mode.setNavigationIcon(changedProfile.navigationIcon);
RouteLineHelper.saveRouteLineAppearance(app, mode, changedProfile.routeLineDrawInfo);
FragmentActivity activity = getActivity(); FragmentActivity activity = getActivity();
if (activity != null) { if (activity != null) {
@ -798,6 +806,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
if (!ApplicationMode.values(app).contains(mode)) { if (!ApplicationMode.values(app).contains(mode)) {
ApplicationMode.changeProfileAvailability(mode, true, app); ApplicationMode.changeProfileAvailability(mode, true, app);
} }
RouteLineHelper.saveRouteLineAppearance(app, mode, changedProfile.routeLineDrawInfo);
return mode; return mode;
} }
@ -989,7 +998,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
MapActivity mapActivity = getMapActivity(); MapActivity mapActivity = getMapActivity();
ApplicationMode appMode = getSelectedAppMode(); ApplicationMode appMode = getSelectedAppMode();
if (mapActivity != null && appMode != null) { if (mapActivity != null && appMode != null) {
RouteLineAppearanceFragment.showInstance(mapActivity, appMode, this); RouteLineAppearanceFragment.showInstance(mapActivity, changedProfile.routeLineDrawInfo, appMode, this);
} }
} }
return super.onPreferenceClick(preference); return super.onPreferenceClick(preference);
@ -1005,6 +1014,11 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
this.onCardPressed(colorsCard); this.onCardPressed(colorsCard);
} }
@Override
public void applyRouteLineAppearance(@NonNull RouteLineDrawInfo routeLineDrawInfo) {
changedProfile.routeLineDrawInfo = routeLineDrawInfo;
}
public static boolean showInstance(FragmentActivity activity, SettingsScreenType screenType, @Nullable String appMode, boolean imported) { public static boolean showInstance(FragmentActivity activity, SettingsScreenType screenType, @Nullable String appMode, boolean imported) {
try { try {
Fragment fragment = Fragment.instantiate(activity, screenType.fragmentName); Fragment fragment = Fragment.instantiate(activity, screenType.fragmentName);
@ -1036,6 +1050,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
RouteService routeService; RouteService routeService;
NavigationIcon navigationIcon; NavigationIcon navigationIcon;
LocationIcon locationIcon; LocationIcon locationIcon;
RouteLineDrawInfo routeLineDrawInfo;
@ColorInt @ColorInt
public int getActualColor() { public int getActualColor() {
@ -1072,6 +1087,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
return false; return false;
if (routeService != that.routeService) return false; if (routeService != that.routeService) return false;
if (navigationIcon != that.navigationIcon) return false; if (navigationIcon != that.navigationIcon) return false;
if (routeLineDrawInfo != that.routeLineDrawInfo) return false;
return locationIcon == that.locationIcon; return locationIcon == that.locationIcon;
} }
@ -1087,6 +1103,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
result = 31 * result + (routeService != null ? routeService.hashCode() : 0); result = 31 * result + (routeService != null ? routeService.hashCode() : 0);
result = 31 * result + (navigationIcon != null ? navigationIcon.hashCode() : 0); result = 31 * result + (navigationIcon != null ? navigationIcon.hashCode() : 0);
result = 31 * result + (locationIcon != null ? locationIcon.hashCode() : 0); result = 31 * result + (locationIcon != null ? locationIcon.hashCode() : 0);
result = 31 * result + (routeLineDrawInfo != null ? routeLineDrawInfo.hashCode() : 0);
return result; return result;
} }
} }

View file

@ -10,6 +10,7 @@ import android.view.ViewTreeObserver;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ScrollView;
import androidx.activity.OnBackPressedCallback; import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -19,26 +20,45 @@ import androidx.fragment.app.FragmentActivity;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.plus.LockableScrollView; import net.osmand.plus.LockableScrollView;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.UiUtilities; import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.DialogButtonType; import net.osmand.plus.UiUtilities.DialogButtonType;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.ContextMenuScrollFragment; import net.osmand.plus.base.ContextMenuScrollFragment;
import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.enums.DayNightMode;
import net.osmand.plus.routing.RouteLineDrawInfo;
import net.osmand.plus.routing.cards.RouteLineColorCard;
import net.osmand.plus.routing.cards.RouteLineColorCard.OnMapThemeUpdateListener;
import net.osmand.plus.routing.cards.RouteLineColorCard.OnSelectedColorChangeListener;
import net.osmand.plus.routing.cards.RouteLineWidthCard;
import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener;
import net.osmand.plus.track.TrackAppearanceFragment.OnNeedScrollListener;
public class RouteLineAppearanceFragment extends ContextMenuScrollFragment { public class RouteLineAppearanceFragment extends ContextMenuScrollFragment implements ColorPickerListener, OnSelectedColorChangeListener, OnMapThemeUpdateListener {
public final static String TAG = RouteLineAppearanceFragment.class.getName(); public static final String TAG = RouteLineAppearanceFragment.class.getName();
private static final String INIT_MAP_THEME = "init_map_theme";
private static final String SELECTED_MAP_THEME = "selected_map_theme";
private ApplicationMode appMode; private ApplicationMode appMode;
private RouteLineDrawInfo routeLineDrawInfo;
private int toolbarHeightPx; private int toolbarHeightPx;
private DayNightMode initMapTheme;
private DayNightMode selectedMapTheme;
private View buttonsShadow; private View buttonsShadow;
private View controlButtons; private View controlButtons;
private View toolbarContainer; private View toolbarContainer;
private RouteLineColorCard colorCard;
private RouteLineWidthCard widthCard;
@Override @Override
public int getMainLayoutId() { public int getMainLayoutId() {
return R.layout.route_line_appearance; return R.layout.route_line_appearance;
@ -82,8 +102,19 @@ public class RouteLineAppearanceFragment extends ContextMenuScrollFragment {
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
toolbarHeightPx = getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar); toolbarHeightPx = getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar);
requireMyActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
if (savedInstanceState != null) {
routeLineDrawInfo = new RouteLineDrawInfo(savedInstanceState);
initMapTheme = DayNightMode.valueOf(savedInstanceState.getString(INIT_MAP_THEME));
selectedMapTheme = DayNightMode.valueOf(savedInstanceState.getString(SELECTED_MAP_THEME));
} else {
initMapTheme = getMyApplication().getSettings().DAYNIGHT_MODE.get();
selectedMapTheme = initMapTheme;
}
requireMapActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
public void handleOnBackPressed() { public void handleOnBackPressed() {
dismiss(); dismiss();
} }
@ -136,6 +167,36 @@ public class RouteLineAppearanceFragment extends ContextMenuScrollFragment {
private void setupCards() { private void setupCards() {
MapActivity mapActivity = requireMapActivity(); MapActivity mapActivity = requireMapActivity();
ViewGroup cardsContainer = getCardsContainer(); ViewGroup cardsContainer = getCardsContainer();
colorCard = new RouteLineColorCard(mapActivity, this, routeLineDrawInfo, appMode, initMapTheme, selectedMapTheme);
cardsContainer.addView(colorCard.build(mapActivity));
widthCard = new RouteLineWidthCard(mapActivity, routeLineDrawInfo, createScrollListener());
cardsContainer.addView(widthCard.build(mapActivity));
}
private OnNeedScrollListener createScrollListener() {
return new OnNeedScrollListener() {
@Override
public void onVerticalScrollNeeded(int y) {
View view = widthCard.getView();
if (view != null) {
int resultYPosition = view.getTop() + y;
int dialogHeight = getInnerScrollableHeight();
ScrollView scrollView = (ScrollView) getBottomScrollView();
if (resultYPosition > (scrollView.getScrollY() + dialogHeight)) {
scrollView.smoothScrollTo(0, resultYPosition - dialogHeight);
}
}
}
private int getInnerScrollableHeight() {
int totalScreenHeight = getViewHeight() - getMenuStatePosY(getCurrentMenuState());
int frameTotalHeight = controlButtons.getHeight() + buttonsShadow.getHeight();
return totalScreenHeight - frameTotalHeight;
}
};
} }
private void setupToolbar() { private void setupToolbar() {
@ -143,7 +204,6 @@ public class RouteLineAppearanceFragment extends ContextMenuScrollFragment {
closeButton.setOnClickListener(new View.OnClickListener() { closeButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
// discard changes
dismiss(); dismiss();
} }
}); });
@ -172,7 +232,9 @@ public class RouteLineAppearanceFragment extends ContextMenuScrollFragment {
saveButton.setOnClickListener(new View.OnClickListener() { saveButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
// save changes if (getTargetFragment() instanceof OnApplyRouteLineListener) {
((OnApplyRouteLineListener) getTargetFragment()).applyRouteLineAppearance(routeLineDrawInfo);
}
dismiss(); dismiss();
} }
}); });
@ -181,7 +243,6 @@ public class RouteLineAppearanceFragment extends ContextMenuScrollFragment {
cancelButton.setOnClickListener(new View.OnClickListener() { cancelButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
// discard changes
FragmentActivity activity = getActivity(); FragmentActivity activity = getActivity();
if (activity != null) { if (activity != null) {
activity.onBackPressed(); activity.onBackPressed();
@ -225,6 +286,33 @@ public class RouteLineAppearanceFragment extends ContextMenuScrollFragment {
.setDuration(200); .setDuration(200);
} }
@Override
public void onResume() {
super.onResume();
setDrawInfoOnRouteLayer(routeLineDrawInfo);
}
@Override
public void onPause() {
super.onPause();
setDrawInfoOnRouteLayer(null);
}
private void setDrawInfoOnRouteLayer(@Nullable RouteLineDrawInfo drawInfo) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.getMapLayers().getRouteLayer().setRouteLineDrawInfo(drawInfo);
}
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(INIT_MAP_THEME, initMapTheme.name());
outState.putString(SELECTED_MAP_THEME, selectedMapTheme.name());
routeLineDrawInfo.saveToBundle(outState);
}
@Override @Override
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();
@ -250,6 +338,7 @@ public class RouteLineAppearanceFragment extends ContextMenuScrollFragment {
R.id.map_right_widgets_panel, R.id.map_right_widgets_panel,
R.id.map_center_info, R.id.map_center_info,
R.id.map_search_button); R.id.map_search_button);
changeMapTheme(initMapTheme);
} }
} }
@ -271,13 +360,30 @@ public class RouteLineAppearanceFragment extends ContextMenuScrollFragment {
} }
} }
@Override
public void onColorSelected(Integer prevColor, int newColor) {
colorCard.onColorSelected(prevColor, newColor);
}
@Override
public void onSelectedColorChanged() {
if (widthCard != null) {
widthCard.updateItems();
}
if (getMapActivity() != null) {
getMapActivity().refreshMap();
}
}
public static boolean showInstance(@NonNull MapActivity mapActivity, public static boolean showInstance(@NonNull MapActivity mapActivity,
@NonNull RouteLineDrawInfo drawInfo,
@NonNull ApplicationMode appMode, @NonNull ApplicationMode appMode,
@NonNull Fragment target) { @NonNull Fragment target) {
try { try {
RouteLineAppearanceFragment fragment = new RouteLineAppearanceFragment(); RouteLineAppearanceFragment fragment = new RouteLineAppearanceFragment();
fragment.setRetainInstance(true); fragment.setRetainInstance(true);
fragment.setTargetFragment(target, 0); fragment.setTargetFragment(target, 0);
fragment.routeLineDrawInfo = new RouteLineDrawInfo(drawInfo);
fragment.appMode = appMode; fragment.appMode = appMode;
mapActivity.getSupportFragmentManager() mapActivity.getSupportFragmentManager()
@ -290,4 +396,21 @@ public class RouteLineAppearanceFragment extends ContextMenuScrollFragment {
return false; return false;
} }
} }
@Override
public void onMapThemeUpdated(@NonNull DayNightMode mapTheme) {
changeMapTheme(mapTheme);
}
private void changeMapTheme(@NonNull DayNightMode mapTheme) {
OsmandApplication app = getMyApplication();
if (app != null) {
app.getSettings().DAYNIGHT_MODE.set(mapTheme);
selectedMapTheme = mapTheme;
}
}
public interface OnApplyRouteLineListener {
void applyRouteLineAppearance(@NonNull RouteLineDrawInfo routeLineDrawInfo);
}
} }

View file

@ -32,6 +32,7 @@ import net.osmand.plus.measurementtool.MeasurementToolFragment;
import net.osmand.plus.profiles.LocationIcon; import net.osmand.plus.profiles.LocationIcon;
import net.osmand.plus.routing.RouteCalculationResult; import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RouteLineDrawInfo;
import net.osmand.plus.routing.RouteService; import net.osmand.plus.routing.RouteService;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper; import net.osmand.plus.routing.TransportRoutingHelper;
@ -67,6 +68,7 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
private LayerDrawable selectedPoint; private LayerDrawable selectedPoint;
private TrackChartPoints trackChartPoints; private TrackChartPoints trackChartPoints;
private RouteLineDrawInfo routeLineDrawInfo;
private RenderingLineAttributes attrs; private RenderingLineAttributes attrs;
private RenderingLineAttributes attrsPT; private RenderingLineAttributes attrsPT;
@ -217,10 +219,11 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
} }
public boolean isInRouteLineAppearanceMode() { public boolean isInRouteLineAppearanceMode() {
MapActivity mapActivity = getMapActivity(); return routeLineDrawInfo != null;
return mapActivity != null }
&& mapActivity.getRouteLineAppearanceFragment() != null
&& mapActivity.getRouteLineAppearanceFragment().isVisible(); public void setRouteLineDrawInfo(RouteLineDrawInfo routeLineDrawInfo) {
this.routeLineDrawInfo = routeLineDrawInfo;
} }
private MapActivity getMapActivity() { private MapActivity getMapActivity() {
@ -277,9 +280,13 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
} }
} }
} }
@Override @Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {} public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (routeLineDrawInfo != null) {
// draw route line on map
}
}
private void drawAction(RotatedTileBox tb, Canvas canvas, List<Location> actionPoints) { private void drawAction(RotatedTileBox tb, Canvas canvas, List<Location> actionPoints) {
if (actionPoints.size() > 0) { if (actionPoints.size() > 0) {