Fix #8634 Vehicle parameters numeric dialog

This commit is contained in:
Dima-1 2020-06-02 21:17:05 +03:00
parent 725533afdd
commit a4263312ef
9 changed files with 448 additions and 7 deletions

View file

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="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">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding">
<LinearLayout
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:baselineAligned="false">
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox"
android:id="@+id/text_caption"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:hintEnabled="false"
android:gravity="start"
android:layout_weight="1"
app:boxBackgroundColor="@color/material_text_input_layout_bg">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/text_edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:inputType="numberDecimal"
android:maxLines="1"
android:maxLength="5"
android:minHeight="@dimen/favorites_list_item_height"
android:paddingBottom="@dimen/card_content_padding_large"
android:paddingStart="@dimen/content_padding_small"
android:paddingLeft="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding_small"
android:paddingEnd="@dimen/content_padding_small"
android:textSize="@dimen/default_list_text_size"
tools:text="@string/lorem_ipsum" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<TextView
android:id="@+id/metric"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding_small"
android:paddingEnd="@dimen/content_padding_small"
android:paddingLeft="@dimen/content_padding_small"
android:text="@string/shared_string_meters" />
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/content_padding_small"
android:paddingBottom="@dimen/content_padding_small"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingStart="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:clipToPadding="false"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="@layout/point_editor_icon_category_item" />
</LinearLayout>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<net.osmand.plus.widgets.TextViewEx xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:minHeight="@dimen/bottom_sheet_list_item_height"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
android:lineSpacingMultiplier="@dimen/bottom_sheet_info_spacing_multiplier"
app:typeface="@string/font_roboto_regular"
tools:text="@string/weight_limit_description"
android:paddingEnd="@dimen/content_padding"
android:paddingStart="@dimen/content_padding" />

View file

@ -75,7 +75,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/shared_string_name"
app:boxBackgroundColor="#4DCCCCCC">
app:boxBackgroundColor="@color/material_text_input_layout_bg">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/name_edit"
@ -128,7 +128,7 @@
android:layout_marginRight="@dimen/content_padding"
android:layout_weight="1"
android:hint="@string/shared_string_description"
app:boxBackgroundColor="#4DCCCCCC">
app:boxBackgroundColor="@color/material_text_input_layout_bg">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/description_edit"

View file

@ -21,6 +21,7 @@
<color name="app_bar_color_dark">#252727</color>
<color name="status_bar_color_light">#e68200</color>
<color name="status_bar_color_dark">#232525</color>
<color name="material_text_input_layout_bg">#4DCCCCCC</color>
<color name="active_buttons_and_links_bg_pressed_light">#0f67eb</color>
<color name="active_buttons_and_links_bg_pressed_dark">#b87114</color>

View file

@ -270,6 +270,7 @@
<dimen name="bottom_sheet_image_text_margin_start">10dp</dimen>
<dimen name="bottom_sheet_selected_item_title_height">56dp</dimen>
<dimen name="bottom_sheet_text_spacing_multiplier" format="float">1.25</dimen>
<dimen name="bottom_sheet_info_spacing_multiplier" format="float">1.5</dimen>
<dimen name="bottom_sheet_big_item_height">128dp</dimen>
<dimen name="action_bar_image_width_land">236dp</dimen>

View file

@ -11,6 +11,8 @@
Thx - Hardy
-->
<string name="shared_string_meters">meters</string>
<string name="shared_string_tones">tones</string>
<string name="default_screen_timeout">Default screen timeout</string>
<string name="screen_timeout_descr">If the \"%1$s\" option is enabled, the activity time will depend on it.</string>
<string name="keep_screen_off">Keep screen off</string>
@ -28,6 +30,9 @@
<string name="screen_control">Screen control</string>
<string name="shared_string_always">Always</string>
<string name="gpx_parse_error">OsmAnd GPX is not well formed, please contact support team to investigate further</string>
<string name="weight_limit_description">Provide your vehicle weight, some routes restrictions may be applied for heavy vehicles.</string>
<string name="height_limit_description">Provide your vehicle height, some routes restrictions may apply for high vehicles.</string>
<string name="width_limit_description">Provide your vehicle width some routes restrictions may be applied for wide vehicles.</string>
<string name="unsupported_type_error">Unsupported type</string>
<string name="index_item_world_basemap_detailed">World overview map (detailed)</string>
<string name="profiles_for_action_not_found">Could not find any such profiles.</string>

View file

@ -0,0 +1,214 @@
package net.osmand.plus.settings.bottomsheets;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.mapcontextmenu.editors.IconCategoriesAdapter;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.fragments.ApplyQueryType;
import net.osmand.plus.settings.fragments.OnConfirmPreferenceChange;
import net.osmand.plus.settings.preferences.SizePreference;
import net.osmand.router.GeneralRouter;
import net.osmand.util.Algorithms;
import java.util.Arrays;
public class VehicleParametersNumericBottomSheet extends BasePreferenceBottomSheet {
public enum VehicleSizeAssets {
WIDTH(GeneralRouter.VEHICLE_WIDTH, R.drawable.img_help_width_limit_day, R.drawable.img_help_width_limit_night,
R.string.width_limit_description, R.string.shared_string_meters, R.string.m),
HEIGHT(GeneralRouter.VEHICLE_HEIGHT, R.drawable.img_help_height_limit_day, R.drawable.img_help_height_limit_night,
R.string.height_limit_description, R.string.shared_string_meters, R.string.m),
WEIGHT(GeneralRouter.VEHICLE_WEIGHT, R.drawable.img_help_weight_limit_day, R.drawable.img_help_weight_limit_night,
R.string.weight_limit_description, R.string.shared_string_tones, R.string.metric_ton);
String routerParameterName;
int dayIconId;
int nightIconId;
int descriptionRes;
int metricRes;
int metricShortRes;
VehicleSizeAssets(String routerParameterName, int dayIconId, int nightIconId, int descriptionRes, int metricRes,
int metricShortRes) {
this.routerParameterName = routerParameterName;
this.dayIconId = dayIconId;
this.nightIconId = nightIconId;
this.descriptionRes = descriptionRes;
this.metricRes = metricRes;
this.metricShortRes = metricShortRes;
}
public static VehicleSizeAssets getAssets(String parameterName) {
for (VehicleSizeAssets type : VehicleSizeAssets.values()) {
if (type.routerParameterName.equals(parameterName)) {
return type;
}
}
return null;
}
public int getDayIconId() {
return dayIconId;
}
public int getNightIconId() {
return nightIconId;
}
public int getDescriptionRes() {
return descriptionRes;
}
public int getMetricRes() {
return metricRes;
}
public int getMetricShortRes() {
return metricShortRes;
}
}
public static final String TAG = VehicleParametersNumericBottomSheet.class.getSimpleName();
private String selectedItem;
private float currentValue;
@Override
public void createMenuItems(Bundle savedInstanceState) {
OsmandApplication app = getMyApplication();
if (app == null) {
return;
}
SizePreference preference = (SizePreference) getPreference();
String key = preference.getKey();
String parameterName = key.substring(key.lastIndexOf("_") + 1);
VehicleSizeAssets vehicleSizeAssets = VehicleSizeAssets.getAssets(parameterName);
if (vehicleSizeAssets == null) {
return;
}
items.add(new TitleItem(preference.getTitle().toString()));
ImageView imageView = new ImageView(getContext());
imageView.setImageDrawable(ContextCompat.getDrawable(app,
!nightMode ? vehicleSizeAssets.getDayIconId() : vehicleSizeAssets.getNightIconId()));
items.add(new SimpleBottomSheetItem.Builder().setCustomView(imageView).create());
items.add(new DividerSpaceItem(app, getResources().getDimensionPixelSize(R.dimen.bottom_sheet_content_margin_small)));
BaseBottomSheetItem description = new BottomSheetItemWithDescription.Builder()
.setDescription(app.getString(vehicleSizeAssets.getDescriptionRes()))
.setLayoutId(R.layout.bottom_sheet_item_preference_info)
.create();
items.add(description);
items.add(new DividerSpaceItem(app, getResources().getDimensionPixelSize(R.dimen.bottom_sheet_content_margin_small)));
items.add(createComboView(app, preference));
}
private BaseBottomSheetItem createComboView(OsmandApplication app, final SizePreference preference) {
View mainView = UiUtilities.getMaterialInflater(app, nightMode)
.inflate(R.layout.bottom_sheet_item_edit_with_recyclerview, null);
final IconCategoriesAdapter adapter = new IconCategoriesAdapter(app);
final TextView metric = mainView.findViewById(R.id.metric);
metric.setText(app.getString(preference.getAssets().getMetricRes()));
final TextView text = mainView.findViewById(R.id.text_edit);
currentValue = Float.parseFloat(preference.getValue());
selectedItem = preference.getEntryFromValue(preference.getValue());
String currentValueStr = currentValue == 0.0f ? "" : String.valueOf(currentValue + 0.01f);
text.setText(currentValueStr);
text.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (!Algorithms.isEmpty(s)) {
currentValue = Float.parseFloat(s.toString()) - 0.01f;
} else {
currentValue = 0.0f;
}
selectedItem = preference.getEntryFromValue(String.valueOf(currentValue));
adapter.notifyDataSetChanged();
}
});
adapter.setItems(Arrays.asList(preference.getEntries()));
adapter.setListenerCategory(new IconCategoriesAdapter.IconCategoriesAdapterListener() {
@Override
public void onItemClick(String item) {
selectedItem = item;
currentValue = preference.getValueFromEntries(selectedItem);
String currentValueStr = currentValue == 0.0f ? "" : String.valueOf(currentValue + 0.01f);
text.setText(currentValueStr);
adapter.notifyDataSetChanged();
}
@Override
public String getSelectedItem() {
return selectedItem;
}
});
RecyclerView recyclerView = mainView.findViewById(R.id.recycler_view);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
return new BaseBottomSheetItem.Builder()
.setCustomView(mainView)
.create();
}
@Override
protected int getRightBottomButtonTextId() {
return R.string.shared_string_apply;
}
@Override
protected void onRightBottomButtonClick() {
Fragment target = getTargetFragment();
if (target instanceof OnConfirmPreferenceChange) {
((OnConfirmPreferenceChange) target).onConfirmPreferenceChange(
getPreference().getKey(), String.valueOf(currentValue), ApplyQueryType.BOTTOM_SHEET);
}
dismiss();
}
public static boolean showInstance(@NonNull FragmentManager fragmentManager, String key, Fragment target,
boolean usedOnMap, @Nullable ApplicationMode appMode) {
try {
Bundle args = new Bundle();
args.putString(PREFERENCE_ID, key);
VehicleParametersNumericBottomSheet fragment = new VehicleParametersNumericBottomSheet();
fragment.setArguments(args);
fragment.setUsedOnMap(usedOnMap);
fragment.setAppMode(appMode);
fragment.setTargetFragment(target, 0);
fragment.show(fragmentManager, TAG);
return true;
} catch (RuntimeException e) {
return false;
}
}
}

View file

@ -4,6 +4,7 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.widget.ImageView;
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
@ -14,7 +15,9 @@ import net.osmand.plus.routing.RouteProvider.RouteService;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.bottomsheets.VehicleParametersNumericBottomSheet;
import net.osmand.plus.settings.preferences.ListPreferenceEx;
import net.osmand.plus.settings.preferences.SizePreference;
import net.osmand.router.GeneralRouter;
import java.util.Map;
@ -78,17 +81,29 @@ public class VehicleParametersFragment extends BaseSettingsFragment implements O
String defValue = parameter.getType() == GeneralRouter.RoutingParameterType.NUMERIC ? ROUTING_PARAMETER_NUMERIC_DEFAULT : ROUTING_PARAMETER_SYMBOLIC_DEFAULT;
OsmandSettings.StringPreference pref = (OsmandSettings.StringPreference) app.getSettings().getCustomRoutingProperty(parameterId, defValue);
Object[] values = parameter.getPossibleValues();
String[] valuesStr = new String[values.length];
for (int i = 0; i < values.length; i++) {
valuesStr[i] = values[i].toString();
}
String[] entriesStr = parameter.getPossibleValueDescriptions().clone();
entriesStr[0] = app.getString(R.string.shared_string_none);
ListPreferenceEx listPreference = createListPreferenceEx(pref.getId(), parameter.getPossibleValueDescriptions(), valuesStr, title, R.layout.preference_with_descr);
listPreference.setDescription(description);
listPreference.setIcon(getPreferenceIcon(parameterId));
getPreferenceScreen().addPreference(listPreference);
Context ctx = getContext();
if (ctx == null) {
return;
}
SizePreference vehicleSizePref = new SizePreference(ctx);
vehicleSizePref.setKey(pref.getId());
vehicleSizePref.setAssets(VehicleParametersNumericBottomSheet.VehicleSizeAssets.getAssets(parameterId));
vehicleSizePref.setDefaultValue(defValue);
vehicleSizePref.setTitle(title);
vehicleSizePref.setEntries(entriesStr);
vehicleSizePref.setEntryValues(valuesStr);
vehicleSizePref.setSummary(description);
vehicleSizePref.setIcon(getPreferenceIcon(parameterId));
vehicleSizePref.setLayoutResource(R.layout.preference_with_descr);
getPreferenceScreen().addPreference(vehicleSizePref);
}
private void setupDefaultSpeedPref() {
@ -130,6 +145,18 @@ public class VehicleParametersFragment extends BaseSettingsFragment implements O
return super.onPreferenceClick(preference);
}
@Override
public void onDisplayPreferenceDialog(Preference preference) {
if (preference instanceof SizePreference) {
FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null) {
VehicleParametersNumericBottomSheet.showInstance(getFragmentManager(), preference.getKey(), this, false, getSelectedAppMode());
}
} else {
super.onDisplayPreferenceDialog(preference);
}
}
@Override
public void onPreferenceChanged(String prefId) {
recalculateRoute();

View file

@ -0,0 +1,92 @@
package net.osmand.plus.settings.preferences;
import android.content.Context;
import androidx.preference.DialogPreference;
import net.osmand.plus.R;
import static net.osmand.plus.settings.bottomsheets.VehicleParametersNumericBottomSheet.*;
public class SizePreference extends DialogPreference {
private String[] entries;
private Object[] entryValues;
private String description;
private VehicleSizeAssets assets;
public VehicleSizeAssets getAssets() {
return assets;
}
public void setAssets(VehicleSizeAssets assets) {
this.assets = assets;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
private String defaultValue;
public SizePreference(Context context) {
super(context);
}
public String[] getEntries() {
return entries;
}
public void setEntries(String[] entries) {
this.entries = entries;
}
public Object[] getEntryValues() {
return entryValues;
}
public void setEntryValues(Object[] entryValues) {
this.entryValues = entryValues;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getEntryFromValue(String value) {
for (int i = 0; i < entryValues.length; i++) {
if (entryValues[i].equals(value)) {
return entries[i];
}
}
return "";
}
public float getValueFromEntries(String item) {
String[] entries = getEntries();
for (int i = 0; i < entries.length; i++) {
if (entries[i].equals(item)) {
return Float.parseFloat(getEntryValues()[i].toString());
}
}
return 0.0f;
}
@Override
public CharSequence getSummary() {
String persistedString = getValue();
if (!persistedString.equals(defaultValue)) {
persistedString = String.valueOf(Float.parseFloat(persistedString) + 0.01f);
return String.format(getContext().getString(R.string.ltr_or_rtl_combine_via_space), persistedString, getContext().getString(assets.getMetricShortRes()));
}
return "-";
}
public String getValue() {
return getPersistedString(defaultValue);
}
}