diff --git a/OsmAnd/res/layout/bottom_sheet_item_edit_with_recyclerview.xml b/OsmAnd/res/layout/bottom_sheet_item_edit_with_recyclerview.xml new file mode 100644 index 0000000000..39c3cc29e7 --- /dev/null +++ b/OsmAnd/res/layout/bottom_sheet_item_edit_with_recyclerview.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd/res/layout/bottom_sheet_item_preference_info.xml b/OsmAnd/res/layout/bottom_sheet_item_preference_info.xml new file mode 100644 index 0000000000..528e1206c9 --- /dev/null +++ b/OsmAnd/res/layout/bottom_sheet_item_preference_info.xml @@ -0,0 +1,20 @@ + + \ No newline at end of file diff --git a/OsmAnd/res/layout/point_editor_fragment_new.xml b/OsmAnd/res/layout/point_editor_fragment_new.xml index f9000f7492..972d6bbb5f 100644 --- a/OsmAnd/res/layout/point_editor_fragment_new.xml +++ b/OsmAnd/res/layout/point_editor_fragment_new.xml @@ -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"> + app:boxBackgroundColor="@color/material_text_input_layout_bg"> #252727 #e68200 #232525 + #4DCCCCCC #0f67eb #b87114 diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index 8f6a9e92ab..5e22e66f86 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -270,6 +270,7 @@ 10dp 56dp 1.25 + 1.5 128dp 236dp diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index fca05e36a0..394c037039 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,8 @@ Thx - Hardy --> + meters + tones Default screen timeout If the \"%1$s\" option is enabled, the activity time will depend on it. Keep screen off @@ -28,6 +30,9 @@ Screen control Always OsmAnd GPX is not well formed, please contact support team to investigate further + Provide your vehicle weight, some routes restrictions may be applied for heavy vehicles. + Provide your vehicle height, some routes restrictions may apply for high vehicles. + Provide your vehicle width some routes restrictions may be applied for wide vehicles. Unsupported type World overview map (detailed) Could not find any such profiles. diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/VehicleParametersNumericBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/VehicleParametersNumericBottomSheet.java new file mode 100644 index 0000000000..79b5b53ce3 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/VehicleParametersNumericBottomSheet.java @@ -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; + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/VehicleParametersFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/VehicleParametersFragment.java index 14ff53106b..591d7930f6 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/VehicleParametersFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/VehicleParametersFragment.java @@ -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(); diff --git a/OsmAnd/src/net/osmand/plus/settings/preferences/SizePreference.java b/OsmAnd/src/net/osmand/plus/settings/preferences/SizePreference.java new file mode 100644 index 0000000000..edeb8063b4 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/preferences/SizePreference.java @@ -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); + } +}