Track appearance screen first part

This commit is contained in:
Vitaliy 2020-07-13 19:17:34 +03:00
parent 7038311bae
commit d88bf79930
10 changed files with 763 additions and 21 deletions

View file

@ -37,15 +37,17 @@
tools:text="255" />
</LinearLayout>
<TextView
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/groupName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_padding_half"
android:paddingStart="@dimen/content_padding_half"
android:paddingRight="@dimen/content_padding_half"
android:paddingLeft="@dimen/content_padding_half"
android:paddingTop="@dimen/list_content_padding_large"
android:paddingEnd="@dimen/content_padding_half"
android:paddingTop="@dimen/list_content_padding_large"
android:paddingRight="@dimen/content_padding_half"
android:textColor="?attr/active_color_basic"
app:typeface="@string/font_roboto_medium"
tools:text="@string/favorite" />
</FrameLayout>

View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="match_parent"
android:background="@color/color_transparent">
<net.osmand.plus.mapcontextmenu.InterceptorLinearLayout
android:id="@+id/main_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/context_menu_top_shadow" />
<LinearLayout
android:id="@+id/route_menu_top_shadow_all"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/card_and_list_background_basic"
android:minHeight="@dimen/bottom_sheet_title_height"
android:orientation="vertical"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<View
android:layout_width="@dimen/content_padding"
android:layout_height="2dp"
android:layout_gravity="center"
android:layout_marginTop="@dimen/context_menu_padding_margin_tiny"
android:layout_marginBottom="@dimen/list_item_button_padding"
android:background="?attr/secondary_icon_color" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/no_search_results_description"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:gravity="center_vertical"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:text="@string/shared_string_appearance"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/appearance_icon"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_gravity="center_vertical"
osmand:srcCompat="@drawable/ic_action_gpx_width_bold"
tools:tint="@color/description_font_and_bottom_sheet_icons" />
</LinearLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/bottom_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="@drawable/bg_contextmenu_shadow"
android:foregroundGravity="top|fill_horizontal">
<net.osmand.plus.LockableScrollView
android:id="@+id/route_menu_bottom_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/route_info_bg">
<LinearLayout
android:id="@+id/route_menu_cards_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/route_info_bg"
android:orientation="vertical"
android:paddingBottom="30dp">
</LinearLayout>
</net.osmand.plus.LockableScrollView>
</FrameLayout>
</net.osmand.plus.mapcontextmenu.InterceptorLinearLayout>
<LinearLayout
android:id="@+id/control_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/buttons_shadow"
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_gravity="bottom"
android:background="@drawable/bg_contextmenu_shadow_top_light" />
<include
layout="@layout/bottom_buttons"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_ex_height"
android:layout_gravity="bottom" />
</LinearLayout>
</FrameLayout>

View file

@ -0,0 +1,112 @@
<?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"
android:orientation="vertical">
<include
android:id="@+id/header_view"
layout="@layout/bottom_sheet_item_with_right_descr" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="@dimen/context_menu_padding_margin_tiny"
android:paddingBottom="@dimen/content_padding">
<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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingTop="@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:textColorPrimary"
android:textSize="@dimen/default_list_text_size" />
</LinearLayout>
<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:gravity="start"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size" />
<com.google.android.material.slider.Slider
android:id="@+id/width_slider"
style="@style/Widget.Styled.Slider"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_weight="1"
android:stepSize="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:gravity="end"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -3817,4 +3817,6 @@
<string name="app_mode_motor_scooter">Мотороллер</string>
<string name="osm_edit_closed_note">Закрытая заметка OSM</string>
<string name="app_mode_wheelchair">Инвалидная коляска</string>
<string name="gpx_split_interval_none_descr">Выберите нужный вариант разбиения: по времени или по расстоянию.</string>
<string name="gpx_split_interval_descr">Выберите интервал с которым будут отображаться метки с расстоянием или временем на треке.</string>
</resources>

View file

@ -96,7 +96,8 @@
<dimen name="gpx_small_icon_margin">3dp</dimen>
<dimen name="gpx_small_text_margin">14dp</dimen>
<dimen name="gpx_text_top_margin">6dp</dimen>
<dimen name="gpx_group_button_height">60dp</dimen>
<dimen name="gpx_group_button_width">96dp</dimen>
<dimen name="dashboard_parking_left_margin">16dp</dimen>
<dimen name="dashboard_parking_icon_size">48dp</dimen>

View file

@ -11,6 +11,12 @@
Thx - Hardy
-->
<string name="gpx_direction_arrows">Direction arrows</string>
<string name="shared_string_custom">Custom</string>
<string name="gpx_split_interval_none_descr">Select the desired splitting option: by time or by distance.</string>
<string name="gpx_split_interval_descr">Select the interval at which marks with distance or time on the track will be displayed.</string>
<string name="select_track_width">Select width</string>
<string name="track_show_start_finish_icons">Show start finish icons</string>
<string name="osm_edit_closed_note">Closed OSM Note</string>
<string name="app_mode_go_cart">Go-cart</string>
<string name="app_mode_wheelchair_forward">Wheelchair forward</string>

View file

@ -18,10 +18,14 @@ import net.osmand.render.RenderingRuleProperty;
import net.osmand.render.RenderingRulesStorage;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.List;
public class GpxAppearanceAdapter extends ArrayAdapter<GpxAppearanceAdapter.AppearanceListItem> {
public static final String TRACK_WIDTH_BOLD = "bold";
public static final String TRACK_WIDTH_MEDIUM = "medium";
private OsmandApplication app;
private GpxAppearanceAdapterType adapterType;
private int currentColor;
@ -61,14 +65,7 @@ public class GpxAppearanceAdapter extends ArrayAdapter<GpxAppearanceAdapter.Appe
TextView textView = (TextView) v.findViewById(R.id.text1);
textView.setText(item.localizedValue);
if (ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR.equals(item.attrName)) {
int iconId;
if ("bold".equals(item.value)) {
iconId = R.drawable.ic_action_gpx_width_bold;
} else if ("medium".equals(item.value)) {
iconId = R.drawable.ic_action_gpx_width_medium;
} else {
iconId = R.drawable.ic_action_gpx_width_thin;
}
int iconId = getWidthIconId(item.value);
textView.setCompoundDrawablesWithIntrinsicBounds(null, null,
app.getUIUtilities().getPaintedIcon(iconId, currentColor), null);
} else {
@ -87,7 +84,22 @@ public class GpxAppearanceAdapter extends ArrayAdapter<GpxAppearanceAdapter.Appe
return v;
}
public static int getWidthIconId(String widthAttr) {
if (TRACK_WIDTH_BOLD.equals(widthAttr)) {
return R.drawable.ic_action_gpx_width_bold;
} else if (TRACK_WIDTH_MEDIUM.equals(widthAttr)) {
return R.drawable.ic_action_gpx_width_medium;
} else {
return R.drawable.ic_action_gpx_width_thin;
}
}
public void init() {
addAll(getAppearanceItems(app, adapterType));
}
public static List<AppearanceListItem> getAppearanceItems(OsmandApplication app, GpxAppearanceAdapterType adapterType) {
List<AppearanceListItem> items = new ArrayList<>();
RenderingRuleProperty trackWidthProp = null;
RenderingRuleProperty trackColorProp = null;
RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer();
@ -102,30 +114,31 @@ public class GpxAppearanceAdapter extends ArrayAdapter<GpxAppearanceAdapter.Appe
if (trackWidthProp != null) {
AppearanceListItem item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR, "",
SettingsActivity.getStringPropertyValue(getContext(), trackWidthProp.getDefaultValueDescription()));
add(item);
SettingsActivity.getStringPropertyValue(app, trackWidthProp.getDefaultValueDescription()));
items.add(item);
for (int j = 0; j < trackWidthProp.getPossibleValues().length; j++) {
item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR,
trackWidthProp.getPossibleValues()[j],
SettingsActivity.getStringPropertyValue(getContext(), trackWidthProp.getPossibleValues()[j]));
add(item);
SettingsActivity.getStringPropertyValue(app, trackWidthProp.getPossibleValues()[j]));
items.add(item);
}
item.setLastItem(true);
}
if (trackColorProp != null) {
AppearanceListItem item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR, "",
SettingsActivity.getStringPropertyValue(getContext(), trackColorProp.getDefaultValueDescription()),
SettingsActivity.getStringPropertyValue(app, trackColorProp.getDefaultValueDescription()),
parseTrackColor(renderer, ""));
add(item);
items.add(item);
for (int j = 0; j < trackColorProp.getPossibleValues().length; j++) {
item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR,
trackColorProp.getPossibleValues()[j],
SettingsActivity.getStringPropertyValue(getContext(), trackColorProp.getPossibleValues()[j]),
SettingsActivity.getStringPropertyValue(app, trackColorProp.getPossibleValues()[j]),
parseTrackColor(renderer, trackColorProp.getPossibleValues()[j]));
add(item);
items.add(item);
}
item.setLastItem(true);
}
return items;
}
public static int parseTrackColor(RenderingRulesStorage renderer, String colorName) {
@ -195,6 +208,10 @@ public class GpxAppearanceAdapter extends ArrayAdapter<GpxAppearanceAdapter.Appe
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getLocalizedValue() {
return localizedValue;
}

View file

@ -0,0 +1,64 @@
package net.osmand.plus.myplaces;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import java.io.File;
public class DirectionArrowsCard extends BaseCard {
private SelectedGpxFile selectedGpxFile;
public DirectionArrowsCard(@NonNull MapActivity mapActivity, @NonNull SelectedGpxFile selectedGpxFile) {
super(mapActivity);
this.selectedGpxFile = selectedGpxFile;
}
@Override
public int getCardLayoutId() {
return R.layout.bottom_sheet_item_with_switch;
}
@Override
protected void updateContent() {
AndroidUiHelper.updateVisibility(view.findViewById(R.id.icon), false);
TextView titleView = view.findViewById(R.id.title);
titleView.setText(R.string.gpx_direction_arrows);
final CompoundButton compoundButton = view.findViewById(R.id.compound_button);
compoundButton.setChecked(selectedGpxFile.getGpxFile().isShowStartFinish());
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean checked = !compoundButton.isChecked();
compoundButton.setChecked(checked);
setShowArrows(checked);
}
});
}
private void setShowArrows(boolean showArrows) {
if (selectedGpxFile.getGpxFile() != null) {
GPXFile gpxFile = selectedGpxFile.getGpxFile();
gpxFile.setShowArrows(showArrows);
GpxDataItem gpxDataItem = app.getGpxDbHelper().getItem(new File(gpxFile.path));
if (gpxDataItem != null) {
app.getGpxDbHelper().updateShowArrows(gpxDataItem, showArrows);
}
mapActivity.refreshMap();
}
}
}

View file

@ -0,0 +1,164 @@
package net.osmand.plus.myplaces;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import net.osmand.AndroidUtils;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.DialogButtonType;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.ContextMenuFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
public class TrackAppearanceFragment extends ContextMenuFragment {
public static final String SELECTED_TRACK_FILE_PATH = "selected_track_file_path";
private OsmandApplication app;
private SelectedGpxFile selectedGpxFile;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = requireMyApplication();
String gpxFilePath = null;
Bundle arguments = getArguments();
if (savedInstanceState != null && savedInstanceState.containsKey(SELECTED_TRACK_FILE_PATH)) {
gpxFilePath = savedInstanceState.getString(SELECTED_TRACK_FILE_PATH);
}
if (arguments != null && arguments.containsKey(SELECTED_TRACK_FILE_PATH)) {
gpxFilePath = arguments.getString(SELECTED_TRACK_FILE_PATH);
}
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
if (view != null) {
if (isPortrait()) {
updateCardsLayout();
}
updateCards();
updateButtons(view);
if (!isPortrait()) {
int widthNoShadow = getLandscapeNoShadowWidth();
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(widthNoShadow, ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.BOTTOM | Gravity.START;
view.findViewById(R.id.control_buttons).setLayoutParams(params);
}
runLayoutListener();
}
return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString(SELECTED_TRACK_FILE_PATH, selectedGpxFile.getGpxFile().path);
super.onSaveInstanceState(outState);
}
private void updateCardsLayout() {
View mainView = getMainView();
if (mainView != null) {
LinearLayout cardsContainer = getCardsContainer();
View topShadow = getTopShadow();
FrameLayout bottomContainer = getBottomContainer();
if (getCurrentMenuState() == MenuState.HEADER_ONLY) {
topShadow.setVisibility(View.INVISIBLE);
bottomContainer.setBackgroundDrawable(null);
AndroidUtils.setBackground(mainView.getContext(), cardsContainer, isNightMode(), R.drawable.travel_card_bg_light, R.drawable.travel_card_bg_dark);
} else {
topShadow.setVisibility(View.VISIBLE);
AndroidUtils.setBackground(mainView.getContext(), bottomContainer, isNightMode(), R.color.card_and_list_background_light, R.color.card_and_list_background_dark);
AndroidUtils.setBackground(mainView.getContext(), cardsContainer, isNightMode(), R.color.card_and_list_background_light, R.color.card_and_list_background_dark);
}
}
}
private void updateButtons(View view) {
View buttonsContainer = view.findViewById(R.id.buttons_container);
buttonsContainer.setBackgroundColor(AndroidUtils.getColorFromAttr(view.getContext(), R.attr.route_info_bg));
View saveButton = view.findViewById(R.id.right_bottom_button);
saveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
View cancelButton = view.findViewById(R.id.dismiss_button);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
UiUtilities.setupDialogButton(isNightMode(), cancelButton, DialogButtonType.SECONDARY, R.string.shared_string_cancel);
UiUtilities.setupDialogButton(isNightMode(), saveButton, DialogButtonType.PRIMARY, R.string.shared_string_apply);
AndroidUiHelper.updateVisibility(saveButton, true);
AndroidUiHelper.updateVisibility(view.findViewById(R.id.buttons_divider), true);
}
private void updateCards() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
ViewGroup cardsContainer = getCardsContainer();
cardsContainer.removeAllViews();
BaseCard arrowsCard = new DirectionArrowsCard(mapActivity, selectedGpxFile);
cardsContainer.addView(arrowsCard.build(mapActivity));
BaseCard width = new TrackWidthCard(mapActivity, selectedGpxFile);
cardsContainer.addView(width.build(mapActivity));
}
}
@Override
public int getMainLayoutId() {
return R.layout.track_appearance;
}
@Override
public int getHeaderViewHeight() {
return 0;
}
@Override
public boolean isHeaderViewDetached() {
return false;
}
@Override
public int getToolbarHeight() {
return 0;
}
public static boolean showInstance(@NonNull MapActivity mapActivity, TrackAppearanceFragment fragment) {
try {
mapActivity.getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragmentContainer, fragment, fragment.getFragmentTag())
.addToBackStack(fragment.getFragmentTag())
.commitAllowingStateLoss();
return true;
} catch (RuntimeException e) {
return false;
}
}
}

View file

@ -0,0 +1,259 @@
package net.osmand.plus.myplaces;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
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.google.android.material.slider.Slider;
import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.dialogs.GpxAppearanceAdapter;
import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem;
import net.osmand.plus.dialogs.GpxAppearanceAdapter.GpxAppearanceAdapterType;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.util.Algorithms;
import java.io.File;
import java.util.List;
public class TrackWidthCard extends BaseCard {
private final static String CUSTOM_WIDTH = "custom_width";
private final static int CUSTOM_WIDTH_MIN = 1;
private final static int CUSTOM_WIDTH_MAX = 24;
private SelectedGpxFile selectedGpxFile;
private AppearanceListItem selectedItem;
private List<AppearanceListItem> appearanceItems;
public TrackWidthCard(MapActivity mapActivity, SelectedGpxFile selectedGpxFile) {
super(mapActivity);
this.mapActivity = mapActivity;
this.selectedGpxFile = selectedGpxFile;
appearanceItems = getWidthAppearanceItems();
}
@Override
public int getCardLayoutId() {
return R.layout.track_width_card;
}
@Override
protected void updateContent() {
updateHeader();
updateCustomWidthSlider();
RecyclerView groupRecyclerView = view.findViewById(R.id.recycler_view);
groupRecyclerView.setAdapter(new GpxWidthAdapter(appearanceItems));
groupRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
}
private AppearanceListItem getSelectedItem() {
if (selectedItem == null) {
String selectedWidth = selectedGpxFile.getGpxFile().getWidth(null);
for (AppearanceListItem item : appearanceItems) {
if (Algorithms.objectEquals(item.getValue(), selectedWidth)
|| Algorithms.isInt(selectedWidth) && CUSTOM_WIDTH.equals(item.getAttrName())) {
selectedItem = item;
break;
}
}
}
return selectedItem;
}
private List<AppearanceListItem> getWidthAppearanceItems() {
List<AppearanceListItem> items = GpxAppearanceAdapter.getAppearanceItems(app, GpxAppearanceAdapterType.TRACK_WIDTH);
String selectedWidth = selectedGpxFile.getGpxFile().getWidth(null);
String customWidth = Algorithms.isInt(selectedWidth) ? selectedWidth : String.valueOf(CUSTOM_WIDTH_MIN);
items.add(new AppearanceListItem(CUSTOM_WIDTH, customWidth, app.getString(R.string.shared_string_custom)));
return items;
}
private void updateHeader() {
AndroidUiHelper.updateVisibility(view.findViewById(R.id.icon), false);
TextView titleView = view.findViewById(R.id.title);
titleView.setText(R.string.select_track_width);
TextView descriptionView = view.findViewById(R.id.description);
descriptionView.setText(getSelectedItem().getLocalizedValue());
}
private void updateCustomWidthSlider() {
if (CUSTOM_WIDTH.equals(getSelectedItem().getAttrName())) {
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));
String width = getSelectedItem().getValue();
if (!Algorithms.isEmpty(width) && Algorithms.isInt(width)) {
try {
widthSlider.setValue(Integer.parseInt(width));
} catch (NumberFormatException e) {
widthSlider.setValue(1);
}
} else {
widthSlider.setValue(1);
}
final TextView selectedCustomWidth = 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) {
String valueStr = String.valueOf((int) value);
selectedCustomWidth.setText(valueStr);
getSelectedItem().setValue(valueStr);
setGpxWidth(valueStr);
}
}
});
UiUtilities.setupSlider(widthSlider, nightMode, null);
AndroidUiHelper.updateVisibility(view.findViewById(R.id.slider_container), true);
} else {
AndroidUiHelper.updateVisibility(view.findViewById(R.id.slider_container), false);
}
}
private void setGpxWidth(String width) {
if (selectedGpxFile.getGpxFile() != null) {
GPXFile gpxFile = selectedGpxFile.getGpxFile();
gpxFile.setWidth(width);
GpxDataItem gpxDataItem = app.getGpxDbHelper().getItem(new File(gpxFile.path));
if (gpxDataItem != null) {
app.getGpxDbHelper().updateWidth(gpxDataItem, width);
}
mapActivity.refreshMap();
}
}
private class GpxWidthAdapter extends RecyclerView.Adapter<GpxWidthViewHolder> {
private List<AppearanceListItem> items;
private GpxWidthAdapter(List<AppearanceListItem> items) {
this.items = items;
}
@NonNull
@Override
public GpxWidthViewHolder 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);
GpxWidthViewHolder holder = new GpxWidthViewHolder(view);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AndroidUtils.setBackground(app, holder.widthButton, nightMode, R.drawable.ripple_solid_light_6dp,
R.drawable.ripple_solid_dark_6dp);
}
return holder;
}
@Override
public void onBindViewHolder(@NonNull final GpxWidthViewHolder holder, int position) {
AppearanceListItem item = items.get(position);
holder.widthAttrName.setText(item.getLocalizedValue());
updateButtonBg(holder, item);
updateWidthIcon(holder, item);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int prevSelectedPosition = getItemPosition(getSelectedItem());
selectedItem = items.get(holder.getAdapterPosition());
notifyItemChanged(holder.getAdapterPosition());
notifyItemChanged(prevSelectedPosition);
setGpxWidth(selectedItem.getValue());
updateHeader();
updateCustomWidthSlider();
}
});
}
private void updateWidthIcon(GpxWidthViewHolder holder, AppearanceListItem item) {
int color;
if (selectedGpxFile.isShowCurrentTrack()) {
color = app.getSettings().CURRENT_TRACK_COLOR.get();
} else {
color = selectedGpxFile.getGpxFile().getColor(0);
}
int iconId;
if (CUSTOM_WIDTH.equals(item.getAttrName())) {
iconId = R.drawable.ic_action_settings;
color = AndroidUtils.getColorFromAttr(holder.itemView.getContext(), R.attr.active_color_basic);
} else {
iconId = GpxAppearanceAdapter.getWidthIconId(item.getValue());
}
holder.widthIcon.setImageDrawable(app.getUIUtilities().getPaintedIcon(iconId, color));
}
private void updateButtonBg(GpxWidthViewHolder holder, AppearanceListItem item) {
GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
if (rectContourDrawable != null) {
if (getSelectedItem() != null && getSelectedItem().equals(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.widthButton.setImageDrawable(rectContourDrawable);
}
}
@Override
public int getItemCount() {
return items.size();
}
int getItemPosition(AppearanceListItem name) {
return items.indexOf(name);
}
}
private static class GpxWidthViewHolder extends RecyclerView.ViewHolder {
final TextView widthAttrName;
final ImageView widthIcon;
final ImageView widthButton;
GpxWidthViewHolder(View itemView) {
super(itemView);
widthAttrName = itemView.findViewById(R.id.groupName);
widthIcon = itemView.findViewById(R.id.groupIcon);
widthButton = itemView.findViewById(R.id.outlineRect);
}
}
}