diff --git a/OsmAnd/res/layout/speedometer_widget.xml b/OsmAnd/res/layout/speedometer_widget.xml
index 99fc6e75390..07e60f9f141 100644
--- a/OsmAnd/res/layout/speedometer_widget.xml
+++ b/OsmAnd/res/layout/speedometer_widget.xml
@@ -3,11 +3,10 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:padding="@dimen/content_padding_medium"
- android:clipToPadding="false"
android:clipChildren="false"
- >
+ android:clipToPadding="false"
+ android:orientation="horizontal"
+ android:padding="@dimen/content_padding_medium">
+ android:paddingVertical="9dp">
+ tools:ignore="SpUsage"
+ tools:text="KM/H" />
@@ -59,20 +57,22 @@
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_gravity="center"
- android:gravity="center"
android:layout_marginVertical="9dp"
- android:layout_marginStart="-6dp"
- android:layout_marginEnd="6dp"
android:background="@drawable/speed_limit_shape"
android:elevation="2dp"
+ android:gravity="center"
android:orientation="vertical"
+ android:paddingHorizontal="9dp"
+ android:paddingVertical="9dp"
+ android:translationX="-6dp"
android:translationZ="2dp">
-
+
diff --git a/OsmAnd/res/xml/monitoring_settings.xml b/OsmAnd/res/xml/monitoring_settings.xml
index 7eb551315ae..3131e53891d 100644
--- a/OsmAnd/res/xml/monitoring_settings.xml
+++ b/OsmAnd/res/xml/monitoring_settings.xml
@@ -124,7 +124,7 @@
enabledCommands = plugin.getTRIP_RECORDING_VEHICLE_METRICS().getStringsListForProfile(getSelectedAppMode());
if (!Algorithms.isEmpty(enabledCommands)) {
summary = String.valueOf(enabledCommands.size());
+ prefIcon = getActiveIcon(iconId);
}
}
preference.setSummary(summary);
@@ -288,8 +294,7 @@ public void setupObdRecordingPref() {
preference.setVisible(purchased && PluginsHelper.isEnabled(VehicleMetricsPlugin.class));
promo.setVisible(!purchased);
- int iconId = R.drawable.ic_action_car_info;
- preference.setIcon(getPersistentPrefIcon(iconId));
+ preference.setIcon(prefIcon);
promo.setIcon(getContentIcon(iconId));
}
diff --git a/OsmAnd/src/net/osmand/plus/plugins/monitoring/VehicleMetricsRecordingAdapter.java b/OsmAnd/src/net/osmand/plus/plugins/monitoring/VehicleMetricsRecordingAdapter.java
index 2fd42ddf824..3f68515190f 100644
--- a/OsmAnd/src/net/osmand/plus/plugins/monitoring/VehicleMetricsRecordingAdapter.java
+++ b/OsmAnd/src/net/osmand/plus/plugins/monitoring/VehicleMetricsRecordingAdapter.java
@@ -3,6 +3,7 @@
import static net.osmand.plus.plugins.monitoring.VehicleMetricsRecordingFragment.*;
import android.annotation.SuppressLint;
+import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -20,6 +21,7 @@
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
+import net.osmand.plus.utils.AndroidUtils;
import net.osmand.plus.utils.ColorUtilities;
import net.osmand.plus.utils.UiUtilities;
import net.osmand.shared.obd.OBDCommand;
@@ -185,11 +187,13 @@ private void updateIcon(boolean checked, @DrawableRes int iconId) {
class CategoryHolder extends RecyclerView.ViewHolder {
private final View itemView;
private final TextView textView;
+ private final ImageView imageView;
public CategoryHolder(@NonNull View itemView) {
super(itemView);
this.itemView = itemView;
textView = itemView.findViewById(android.R.id.title);
+ imageView = itemView.findViewById(android.R.id.icon);
}
public void bindView(@NonNull VehicleMetricsRecordingCategory category) {
@@ -199,6 +203,13 @@ public void bindView(@NonNull VehicleMetricsRecordingCategory category) {
int dp36 = getDimen(app, R.dimen.showAllButtonHeight);
itemView.setMinimumHeight(dp36);
textView.setText(category.titleId);
+
+ LinearLayout.LayoutParams currentImageParams = (LinearLayout.LayoutParams) imageView.getLayoutParams();
+ int size = app.getResources().getDimensionPixelSize(R.dimen.standard_icon_size);
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(size, size);
+ params.gravity = Gravity.CENTER;
+ params.setMargins(currentImageParams.leftMargin, currentImageParams.topMargin, AndroidUtils.dpToPx(app, 8), currentImageParams.bottomMargin);
+ imageView.setLayoutParams(params);
}
}
diff --git a/OsmAnd/src/net/osmand/plus/plugins/monitoring/VehicleMetricsRecordingFragment.java b/OsmAnd/src/net/osmand/plus/plugins/monitoring/VehicleMetricsRecordingFragment.java
index 0332df4e9f4..c5764ae7981 100644
--- a/OsmAnd/src/net/osmand/plus/plugins/monitoring/VehicleMetricsRecordingFragment.java
+++ b/OsmAnd/src/net/osmand/plus/plugins/monitoring/VehicleMetricsRecordingFragment.java
@@ -11,6 +11,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
@@ -20,6 +21,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.Toolbar;
+import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
@@ -82,6 +84,11 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
updateNightMode();
View view = themedInflater.inflate(R.layout.vehicle_metrics_recording_fragment, container, false);
AndroidUtils.addStatusBarPadding21v(requireMyActivity(), view);
+ Window window = requireMapActivity().getWindow();
+ if (window != null) {
+ window.setStatusBarColor(ContextCompat.getColor(requireMapActivity(), getStatusBarColorId()));
+ AndroidUiHelper.setStatusBarContentColor(window.getDecorView(), nightMode);
+ }
toolbar = view.findViewById(R.id.toolbar);
AppBarLayout appBarLayout = view.findViewById(R.id.app_bar);
@@ -108,7 +115,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
}
updateSelectAllButton();
- setupButtons(view);
+ setupButtons();
setupToolbar();
setupItems();
@@ -116,7 +123,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
}
@SuppressLint("NotifyDataSetChanged")
- private void setupButtons(@NonNull View view) {
+ private void setupButtons() {
selectAllButton.setOnClickListener(v -> {
if (areAllCommandsSelected()) {
selectedCommands.clear();
diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java
index 2740eedd197..812b7b47904 100644
--- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java
+++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java
@@ -318,7 +318,7 @@ public boolean setPreference(String key, Object value, ApplicationMode mode) {
} else if (preference instanceof ListStringPreference listStringPreference) {
if (value instanceof List> || (value == null && listStringPreference.isNullSupported(mode))) {
if (value == null) {
- listStringPreference.setStringsListForProfile(mode,null);
+ listStringPreference.setStringsListForProfile(mode, null);
} else {
List> list = (List>) value;
boolean isListOfString = list.stream().allMatch(element -> element instanceof String);
diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/SpeedometerWidget.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/SpeedometerWidget.java
index 66ea78e5e30..d000a41abaa 100644
--- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/SpeedometerWidget.java
+++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/SpeedometerWidget.java
@@ -55,6 +55,8 @@
import net.osmand.plus.views.mapwidgets.WidgetsVisibilityHelper;
import net.osmand.util.Algorithms;
+import java.util.List;
+
public class SpeedometerWidget {
private final static int PREVIEW_VALUE = 85;
@@ -84,6 +86,11 @@ public class SpeedometerWidget {
private final static int SPEED_LIMIT_SIZE_L = 96;
private final static int SPEED_LIMIT_DESCRIPTION_SIZE_USUAL = 11;
private final static int SPEED_LIMIT_DESCRIPTION_SIZE_CANADA_S = 9;
+ private final static int SPEED_LIMIT_CONTAINER_US_PADDING_S = 7;
+ private final static int SPEED_LIMIT_CONTAINER_US_PADDING_M = 9;
+ private final static int SPEED_LIMIT_CONTAINER_US_PADDING_L = 12;
+ private final static int SPEED_LIMIT_VALUE_WEIGHT = 2;
+ private final static int SPEED_LIMIT_DESCRIPTION_WEIGHT = 1;
private final static int SPEEDOMETER_PADDING_SIDE_S = 9;
private final static int SPEEDOMETER_PADDING_SIDE_ML = 12;
@@ -93,11 +100,6 @@ public class SpeedometerWidget {
private final static int SPEEDOMETER_PADDING_BOTTOM_L = 12;
private final static int SPEEDOMETER_PADDING_SIDE_AA = 12;
private final static int SPEEDOMETER_PADDING_TOP_BOTTOM_AA = 9;
- private final static int US_SPEED_LIMIT_BOTTOM = 18;
- private final static int US_SPEED_LIMIT_BOTTOM_S = 14;
- private final static int US_SPEED_LIMIT_DESCRIPTION_TOP_S = 18;
- private final static int US_SPEED_LIMIT_DESCRIPTION_TOP_M = 24;
- private final static int US_SPEED_LIMIT_DESCRIPTION_TOP_L = 28;
private final static int SPEEDOMETER_UNIT_DESCR_CANADA_SIZE_S = 8;
private final static int SHADOW_SIZE = 4;
@@ -127,6 +129,8 @@ public class SpeedometerWidget {
private float cachedSpeed = UNDEFINED_SPEED;
private String cachedSpeedLimitText;
private boolean lastNightMode;
+ private Integer cachedMetricSystem;
+ private DrivingRegion cachedRegion;
@Nullable
private Bitmap widgetBitmap;
@@ -157,24 +161,29 @@ private void setupWidget() {
return;
}
+ boolean isUsaOrCanada = isUsaOrCanadaRegion();
LinearLayout.LayoutParams speedLimitValueParams = (LinearLayout.LayoutParams) speedLimitValueView.getLayoutParams();
speedLimitValueParams.setMargins(0, 0, 0, 0);
speedLimitValueView.setLayoutParams(speedLimitValueParams);
- AndroidUiHelper.updateVisibility(speedLimitDescription, false);
+ AndroidUiHelper.updateVisibility(speedLimitDescription, isUsaOrCanada);
WidgetSize newWidgetSize = settings.SPEEDOMETER_SIZE.getModeValue(mode);
- if (previousWidgetSize == newWidgetSize) {
+ DrivingRegion newDrivingRegion = settings.DRIVING_REGION.getModeValue(mode);
+ if (previousWidgetSize == newWidgetSize && cachedRegion == newDrivingRegion) {
return;
}
previousWidgetSize = newWidgetSize;
+ cachedRegion = newDrivingRegion;
LinearLayout.LayoutParams speedLimitLayoutParams = (LinearLayout.LayoutParams) speedLimitContainer.getLayoutParams();
speedLimitLayoutParams.gravity = Gravity.CENTER;
LinearLayout.LayoutParams speedometerLayoutParams = (LinearLayout.LayoutParams) speedometerContainer.getLayoutParams();
- if (isUsaOrCanadaRegion()) {
+ if (isUsaOrCanada) {
speedLimitValueParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
- } else{
+ } else {
speedLimitValueParams.height = LinearLayout.LayoutParams.MATCH_PARENT;
}
+
+ int speedLimitPadding;
speedLimitContainer.setLayoutParams(speedLimitLayoutParams);
switch (previousWidgetSize) {
case MEDIUM:
@@ -187,6 +196,8 @@ private void setupWidget() {
speedLimitLayoutParams.height = dpToPx(SPEED_LIMIT_SIZE_M);
speedLimitLayoutParams.width = dpToPx(SPEED_LIMIT_SIZE_M);
speedLimitValueView.setTextSize(TypedValue.COMPLEX_UNIT_SP, SPEED_LIMIT_TEXT_SIZE_M);
+ speedLimitPadding = isUsaOrCanada ? dpToPx(SPEED_LIMIT_CONTAINER_US_PADDING_M) : 0;
+ speedLimitContainer.setPadding(speedLimitPadding, speedLimitPadding, speedLimitPadding, speedLimitPadding);
speedLimitContainer.setLayoutParams(speedLimitLayoutParams);
speedLimitDescription.setTextSize(TypedValue.COMPLEX_UNIT_SP, SPEED_LIMIT_DESCRIPTION_SIZE_USUAL);
break;
@@ -199,6 +210,8 @@ private void setupWidget() {
speedLimitLayoutParams.height = dpToPx(SPEED_LIMIT_SIZE_L);
speedLimitLayoutParams.width = dpToPx(SPEED_LIMIT_SIZE_L);
+ speedLimitPadding = isUsaOrCanada ? dpToPx(SPEED_LIMIT_CONTAINER_US_PADDING_L) : 0;
+ speedLimitContainer.setPadding(speedLimitPadding, speedLimitPadding, speedLimitPadding, speedLimitPadding);
speedLimitContainer.setLayoutParams(speedLimitLayoutParams);
speedLimitValueView.setTextSize(TypedValue.COMPLEX_UNIT_SP, SPEED_LIMIT_TEXT_SIZE_L);
speedLimitDescription.setTextSize(TypedValue.COMPLEX_UNIT_SP, SPEED_LIMIT_DESCRIPTION_SIZE_USUAL);
@@ -212,6 +225,8 @@ private void setupWidget() {
speedLimitLayoutParams.height = dpToPx(SPEED_LIMIT_SIZE_S);
speedLimitLayoutParams.width = dpToPx(SPEED_LIMIT_SIZE_S);
+ speedLimitPadding = isUsaOrCanada ? dpToPx(SPEED_LIMIT_CONTAINER_US_PADDING_S) : 0;
+ speedLimitContainer.setPadding(speedLimitPadding, speedLimitPadding, speedLimitPadding, speedLimitPadding);
speedLimitContainer.setLayoutParams(speedLimitLayoutParams);
speedLimitValueView.setTextSize(TypedValue.COMPLEX_UNIT_SP, SPEED_LIMIT_TEXT_SIZE_S);
speedLimitDescription.setTextSize(TypedValue.COMPLEX_UNIT_SP, isCanadaRegion() ? SPEED_LIMIT_DESCRIPTION_SIZE_CANADA_S : SPEED_LIMIT_DESCRIPTION_SIZE_USUAL);
@@ -255,6 +270,9 @@ public void updateInfo(@Nullable DrawSettings drawSettings, boolean drawBitmap,
lastNightMode = nightMode;
isChanged = true;
}
+ if (isMetricUpdateNeeded()) {
+ isChanged = true;
+ }
Location location = provider.getLastKnownLocation();
if (location != null && location.hasSpeed()) {
float updateThreshold = cachedSpeed < LOW_SPEED_THRESHOLD_MPS
@@ -344,6 +362,15 @@ public void updateInfo(@Nullable DrawSettings drawSettings, boolean drawBitmap,
}
}
+ public boolean isMetricUpdateNeeded() {
+ int metricSystem = app.getSettings().METRIC_SYSTEM.get().ordinal();
+ if (cachedMetricSystem == null || cachedMetricSystem != metricSystem) {
+ cachedMetricSystem = metricSystem;
+ return true;
+ }
+ return false;
+ }
+
private boolean shouldShowWidget() {
boolean showSpeedometerSetting = settings.SHOW_SPEEDOMETER.getModeValue(mode);
if (visibilityHelper != null) {
@@ -428,20 +455,19 @@ private void drawSpeedLimit(Canvas canvas, int textSize, float density, Rect ale
float x = alertRect.left + (float) alertRect.width() / 2 - textPaint.measureText(cachedSpeedLimitText) / 2;
float y;
if (isUsaOrCanadaRegion()) {
- int padding;
- if (newWidgetSize == WidgetSize.SMALL) {
- padding = US_SPEED_LIMIT_BOTTOM_S;
- } else {
- padding = US_SPEED_LIMIT_BOTTOM;
- }
- y = alertRect.bottom - padding * density;
+ Rect contentRect = getSpeedlimitContentRect(alertRect, newWidgetSize, density);
+ y = calculateYWeightPose(contentRect, SPEED_LIMIT_VALUE_WEIGHT, List.of(SPEED_LIMIT_DESCRIPTION_WEIGHT, SPEED_LIMIT_VALUE_WEIGHT), List.of(SPEED_LIMIT_DESCRIPTION_WEIGHT), textBounds);
} else {
y = alertRect.top + (float) alertRect.height() / 2 + (float) textBounds.height() / 2;
}
canvas.drawText(cachedSpeedLimitText, x, y, textPaint);
}
- private void drawSpeedLimitDescription(Canvas canvas, TextPaint textPaint, Rect alertRect, float density, WidgetSize newWidgetSize){
+ private float calculateFrameTextHeight(float weight, float totalWeight, float rectHeight) {
+ return ((weight * rectHeight / totalWeight));
+ }
+
+ private void drawSpeedLimitDescription(Canvas canvas, TextPaint textPaint, Rect alertRect, float density, WidgetSize newWidgetSize) {
float unitTextSize;
String textLimitDescription;
if (isUsaRegion()) {
@@ -455,18 +481,51 @@ private void drawSpeedLimitDescription(Canvas canvas, TextPaint textPaint, Rect
unitTextSize = SPEEDOMETER_UNIT_TEXT_SIZE;
}
}
+ Rect contentRect = getSpeedlimitContentRect(alertRect, newWidgetSize, density);
textPaint.setTextSize(unitTextSize * density);
- float xDescr = alertRect.left + (float) alertRect.width() / 2 - textPaint.measureText(textLimitDescription) / 2;
- int padding;
- if (newWidgetSize == WidgetSize.SMALL) {
- padding = US_SPEED_LIMIT_DESCRIPTION_TOP_S;
- } else if (newWidgetSize == WidgetSize.MEDIUM) {
- padding = US_SPEED_LIMIT_DESCRIPTION_TOP_M;
+ Rect textBounds = new Rect();
+ textPaint.getTextBounds(textLimitDescription, 0, textLimitDescription.length(), textBounds);
+ float xDescr = contentRect.left + (float) contentRect.width() / 2 - textPaint.measureText(textLimitDescription) / 2;
+ float yDescr = calculateYWeightPose(contentRect, SPEED_LIMIT_DESCRIPTION_WEIGHT, List.of(SPEED_LIMIT_VALUE_WEIGHT, SPEED_LIMIT_DESCRIPTION_WEIGHT), null, textBounds);
+
+ canvas.drawText(textLimitDescription, xDescr, yDescr, textPaint);
+ }
+
+ private float calculateYWeightPose(@NonNull Rect contentRect, int frameWeight, @NonNull List allWeights,
+ @Nullable List weightsAbove, @NonNull Rect textBounds) {
+ float halfTextHeight = textBounds.height() / 2.0f;
+ float totalWeight = allWeights.stream().reduce(0, Integer::sum);
+
+ float totalHeightAbove = 0;
+ if (weightsAbove != null) {
+ for (Integer weight : weightsAbove) {
+ totalHeightAbove += calculateFrameTextHeight(weight, totalWeight, contentRect.height());
+ }
+ }
+
+ float calculatedFrameTextHeight = calculateFrameTextHeight(frameWeight, totalWeight, contentRect.height());
+ float frameCenterPosition = calculatedFrameTextHeight / 2 + totalHeightAbove + halfTextHeight;
+ return frameCenterPosition + contentRect.top;
+ }
+
+ private Rect getSpeedlimitContentRect(@NonNull Rect speedlimitRect, @NonNull WidgetSize newWidgetSize, float density) {
+ if (isUsaOrCanadaRegion()) {
+ int padding;
+ if (newWidgetSize == WidgetSize.SMALL) {
+ padding = SPEED_LIMIT_CONTAINER_US_PADDING_S;
+ } else if (newWidgetSize == WidgetSize.MEDIUM) {
+ padding = SPEED_LIMIT_CONTAINER_US_PADDING_M;
+ } else {
+ padding = SPEED_LIMIT_CONTAINER_US_PADDING_L;
+ }
+ float scaledPadding = padding * density;
+ return new Rect((int) (speedlimitRect.left + scaledPadding),
+ (int) (speedlimitRect.top + scaledPadding),
+ (int) (speedlimitRect.right - scaledPadding),
+ (int) (speedlimitRect.bottom - scaledPadding));
} else {
- padding = US_SPEED_LIMIT_DESCRIPTION_TOP_L;
+ return speedlimitRect;
}
- float yDescr = alertRect.top + padding * density;
- canvas.drawText(textLimitDescription, xDescr, yDescr, textPaint);
}
private void drawCurrentSpeed(Canvas canvas, int textSize, Rect speedArea, float density, boolean speedExceed) {
@@ -508,7 +567,7 @@ private void drawCurrentSpeed(Canvas canvas, int textSize, Rect speedArea, float
canvas.drawText(formattedSpeed.value, x, y, textPaint);
}
- private int getSpeedLimitColor(boolean nightMode){
+ private int getSpeedLimitColor(boolean nightMode) {
if (isUsaOrCanadaRegion() || isEuropeRegion()) {
return app.getColor(nightMode ? R.color.widgettext_night : R.color.widgettext_day);
} else {
@@ -609,15 +668,10 @@ private void setSpeedLimitText(String value) {
}
private void setSpeedLimitDescription() {
- boolean visible = false;
- if (isUsaOrCanadaRegion()) {
- if (speedLimitDescription != null) {
- String textLimitDescription = app.getString(isCanadaRegion() ? R.string.speedometer_maximum : R.string.shared_string_limit).toUpperCase();
- speedLimitDescription.setText(textLimitDescription);
- visible = true;
- }
+ if (isUsaOrCanadaRegion() && speedLimitDescription != null) {
+ String textLimitDescription = app.getString(isCanadaRegion() ? R.string.speedometer_maximum : R.string.shared_string_limit).toUpperCase();
+ speedLimitDescription.setText(textLimitDescription);
}
- AndroidUiHelper.updateVisibility(speedLimitDescription, visible);
}
private boolean isUsaOrCanadaRegion() {