forked from organicmaps/organicmaps-tmp
[android] Fix SpeedLimitView
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
This commit is contained in:
parent
c96d873fa8
commit
2c002eb08b
11 changed files with 104 additions and 81 deletions
|
@ -49,6 +49,12 @@ Java_app_organicmaps_util_StringUtils_nativeFilterContainsNormalized(JNIEnv * en
|
|||
return jni::ToJavaStringArray(env, filtered);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_app_organicmaps_util_StringUtils_nativeFormatSpeed(
|
||||
JNIEnv * env, jclass thiz, jdouble metersPerSecond)
|
||||
{
|
||||
return measurement_utils::FormatSpeed(metersPerSecond, measurement_utils::GetMeasurementUnits());
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_app_organicmaps_util_StringUtils_nativeFormatSpeedAndUnits(
|
||||
JNIEnv * env, jclass thiz, jdouble metersPerSecond)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@ import app.organicmaps.Framework;
|
|||
import app.organicmaps.R;
|
||||
import app.organicmaps.location.LocationHelper;
|
||||
import app.organicmaps.maplayer.traffic.TrafficManager;
|
||||
import app.organicmaps.util.StringUtils;
|
||||
import app.organicmaps.util.UiUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.widget.LanesView;
|
||||
|
@ -249,10 +250,10 @@ public class NavigationController implements TrafficManager.TrafficCallback,
|
|||
{
|
||||
final Location location = LocationHelper.from(mFrame.getContext()).getSavedLocation();
|
||||
if (location == null) {
|
||||
mSpeedLimit.setSpeedLimitMps(0);
|
||||
mSpeedLimit.setSpeedLimit(0, false);
|
||||
return;
|
||||
}
|
||||
mSpeedLimit.setCurrentSpeed(location.getSpeed());
|
||||
mSpeedLimit.setSpeedLimitMps(info.speedLimitMps);
|
||||
final boolean speedLimitExceeded = info.speedLimitMps < location.getSpeed();
|
||||
mSpeedLimit.setSpeedLimit(StringUtils.nativeFormatSpeed(info.speedLimitMps), speedLimitExceeded);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ public class StringUtils
|
|||
public static native boolean nativeContainsNormalized(String str, String substr);
|
||||
public static native String[] nativeFilterContainsNormalized(String[] strings, String substr);
|
||||
|
||||
public static native int nativeFormatSpeed(double metersPerSecond);
|
||||
public static native Pair<String, String> nativeFormatSpeedAndUnits(double metersPerSecond);
|
||||
public static native Distance nativeFormatDistance(double meters);
|
||||
@NonNull
|
||||
|
|
|
@ -59,14 +59,14 @@ public class LanesView extends View
|
|||
|
||||
try (TypedArray data = context.getTheme().obtainStyledAttributes(attrs, R.styleable.LanesView, 0, 0))
|
||||
{
|
||||
backgroundColor = getAttrColor(data, R.styleable.LanesView_backgroundColor, DefaultValues.BACKGROUND_COLOR);
|
||||
mActiveLaneTintColor = getAttrColor(data, R.styleable.LanesView_activeLaneTintColor, DefaultValues.ACTIVE_LANE_TINT_COLOR);
|
||||
mInactiveLaneTintColor = getAttrColor(data, R.styleable.LanesView_inactiveLaneTintColor, DefaultValues.INACTIVE_LANE_TINT_COLOR);
|
||||
mCornerRadius = (int) Math.max(data.getDimension(R.styleable.LanesView_cornerRadius, DefaultValues.CORNER_RADIUS), 0.0f);
|
||||
backgroundColor = getAttrColor(data, R.styleable.LanesView_lanesBackgroundColor, DefaultValues.BACKGROUND_COLOR);
|
||||
mActiveLaneTintColor = getAttrColor(data, R.styleable.LanesView_lanesActiveLaneTintColor, DefaultValues.ACTIVE_LANE_TINT_COLOR);
|
||||
mInactiveLaneTintColor = getAttrColor(data, R.styleable.LanesView_lanesInactiveLaneTintColor, DefaultValues.INACTIVE_LANE_TINT_COLOR);
|
||||
mCornerRadius = (int) Math.max(data.getDimension(R.styleable.LanesView_lanesCornerRadius, DefaultValues.CORNER_RADIUS), 0.0f);
|
||||
|
||||
if (isInEditMode())
|
||||
{
|
||||
final int lanesCount = Math.max(1, data.getInt(R.styleable.LanesView_editModeLanesCount, DefaultValues.LANES_COUNT));
|
||||
final int lanesCount = Math.max(1, data.getInt(R.styleable.LanesView_lanesEditModeLanesCount, DefaultValues.LANES_COUNT));
|
||||
createLanesForEditMode(lanesCount);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,16 +8,14 @@ import android.graphics.Paint;
|
|||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.util.StringUtils;
|
||||
|
||||
public class SpeedLimitView extends View
|
||||
{
|
||||
|
@ -26,6 +24,10 @@ public class SpeedLimitView extends View
|
|||
@ColorInt
|
||||
int BACKGROUND_COLOR = Color.WHITE;
|
||||
@ColorInt
|
||||
int BORDER_COLOR = Color.RED;
|
||||
@ColorInt
|
||||
int ALERT_COLOR = Color.RED;
|
||||
@ColorInt
|
||||
int TEXT_COLOR = Color.BLACK;
|
||||
@ColorInt
|
||||
int TEXT_ALERT_COLOR = Color.WHITE;
|
||||
|
@ -61,29 +63,28 @@ public class SpeedLimitView extends View
|
|||
private float mBorderRadius;
|
||||
private float mBorderWidth;
|
||||
|
||||
private double mSpeedLimitMps;
|
||||
@Nullable
|
||||
private String mSpeedLimitStr;
|
||||
|
||||
private double mCurrentSpeed;
|
||||
private int mSpeedLimit = 0;
|
||||
@NonNull
|
||||
private String mSpeedLimitStr = "0";
|
||||
private boolean mAlert = false;
|
||||
|
||||
public SpeedLimitView(Context context, @Nullable AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
|
||||
try (TypedArray data = context.getTheme()
|
||||
.obtainStyledAttributes(attrs, R.styleable.SpeedLimitView, 0, 0))
|
||||
.obtainStyledAttributes(attrs, R.styleable.SpeedLimitView, 0, 0))
|
||||
{
|
||||
mBackgroundColor = data.getColor(R.styleable.SpeedLimitView_BackgroundColor, DefaultValues.BACKGROUND_COLOR);
|
||||
mBorderColor = data.getColor(R.styleable.SpeedLimitView_borderColor, ContextCompat.getColor(context, R.color.base_red));
|
||||
mAlertColor = data.getColor(R.styleable.SpeedLimitView_alertColor, ContextCompat.getColor(context, R.color.base_red));
|
||||
mTextColor = data.getColor(R.styleable.SpeedLimitView_textColor, DefaultValues.TEXT_COLOR);
|
||||
mTextAlertColor = data.getColor(R.styleable.SpeedLimitView_textAlertColor, DefaultValues.TEXT_ALERT_COLOR);
|
||||
mBackgroundColor = data.getColor(R.styleable.SpeedLimitView_speedLimitBackgroundColor, DefaultValues.BACKGROUND_COLOR);
|
||||
mBorderColor = data.getColor(R.styleable.SpeedLimitView_speedLimitBorderColor, DefaultValues.BORDER_COLOR);
|
||||
mAlertColor = data.getColor(R.styleable.SpeedLimitView_speedLimitAlertColor, DefaultValues.ALERT_COLOR);
|
||||
mTextColor = data.getColor(R.styleable.SpeedLimitView_speedLimitTextColor, DefaultValues.TEXT_COLOR);
|
||||
mTextAlertColor = data.getColor(R.styleable.SpeedLimitView_speedLimitTextAlertColor, DefaultValues.TEXT_ALERT_COLOR);
|
||||
if (isInEditMode())
|
||||
{
|
||||
mSpeedLimitMps = data.getInt(R.styleable.SpeedLimitView_editModeSpeedLimit, -1);
|
||||
mSpeedLimitStr = mSpeedLimitMps > 0 ? String.valueOf(((int) mSpeedLimitMps)) : null;
|
||||
mCurrentSpeed = data.getInt(R.styleable.SpeedLimitView_editModeCurrentSpeed, -1);
|
||||
mSpeedLimit = data.getInt(R.styleable.SpeedLimitView_speedLimitEditModeSpeedLimit, 60);
|
||||
mSpeedLimitStr = Integer.toString(mSpeedLimit);
|
||||
mAlert = data.getBoolean(R.styleable.SpeedLimitView_speedLimitEditModeAlert, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,29 +102,19 @@ public class SpeedLimitView extends View
|
|||
mTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
|
||||
}
|
||||
|
||||
public void setSpeedLimitMps(final double speedLimitMps)
|
||||
public void setSpeedLimit(final int speedLimit, boolean alert)
|
||||
{
|
||||
if (mSpeedLimitMps == speedLimitMps)
|
||||
return;
|
||||
final boolean speedLimitChanged = mSpeedLimit != speedLimit;
|
||||
|
||||
mSpeedLimitMps = speedLimitMps;
|
||||
if (mSpeedLimitMps <= 0)
|
||||
mSpeedLimit = speedLimit;
|
||||
mAlert = alert;
|
||||
|
||||
if (speedLimitChanged)
|
||||
{
|
||||
mSpeedLimitStr = null;
|
||||
setVisibility(GONE);
|
||||
return;
|
||||
mSpeedLimitStr = Integer.toString(mSpeedLimit);
|
||||
configureTextSize();
|
||||
}
|
||||
|
||||
final Pair<String, String> speedLimitAndUnits = StringUtils.nativeFormatSpeedAndUnits(mSpeedLimitMps);
|
||||
setVisibility(VISIBLE);
|
||||
mSpeedLimitStr = speedLimitAndUnits.first;
|
||||
configureTextSize();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setCurrentSpeed(final double currentSpeed)
|
||||
{
|
||||
mCurrentSpeed = currentSpeed;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
@ -132,13 +123,15 @@ public class SpeedLimitView extends View
|
|||
{
|
||||
super.onDraw(canvas);
|
||||
|
||||
final boolean alert = mCurrentSpeed > mSpeedLimitMps && mSpeedLimitMps > 0;
|
||||
final boolean validSpeedLimit = mSpeedLimit > 0;
|
||||
if (!validSpeedLimit)
|
||||
return;
|
||||
|
||||
final float cx = mWidth / 2;
|
||||
final float cy = mHeight / 2;
|
||||
|
||||
drawSign(canvas, cx, cy, alert);
|
||||
drawText(canvas, cx, cy, alert);
|
||||
drawSign(canvas, cx, cy, mAlert);
|
||||
drawText(canvas, cx, cy, mAlert);
|
||||
}
|
||||
|
||||
private void drawSign(@NonNull Canvas canvas, float cx, float cy, boolean alert)
|
||||
|
@ -158,9 +151,6 @@ public class SpeedLimitView extends View
|
|||
|
||||
private void drawText(@NonNull Canvas canvas, float cx, float cy, boolean alert)
|
||||
{
|
||||
if (mSpeedLimitStr == null)
|
||||
return;
|
||||
|
||||
if (alert)
|
||||
mTextPaint.setColor(mTextAlertColor);
|
||||
else
|
||||
|
@ -172,6 +162,26 @@ public class SpeedLimitView extends View
|
|||
canvas.drawText(mSpeedLimitStr, cx, textY, mTextPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(@NonNull MotionEvent event)
|
||||
{
|
||||
final float cx = mWidth / 2;
|
||||
final float cy = mHeight / 2;
|
||||
if (Math.pow(event.getX() - cx, 2) + Math.pow(event.getY() - cy, 2) <= Math.pow(mBackgroundRadius, 2))
|
||||
{
|
||||
performClick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performClick()
|
||||
{
|
||||
super.performClick();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
||||
{
|
||||
|
@ -191,9 +201,6 @@ public class SpeedLimitView extends View
|
|||
// Apply binary search to determine the optimal text size that fits within the circular boundary.
|
||||
private void configureTextSize()
|
||||
{
|
||||
if (mSpeedLimitStr == null)
|
||||
return;
|
||||
|
||||
final String text = mSpeedLimitStr;
|
||||
final float textRadius = mBorderRadius - mBorderWidth;
|
||||
final float textMaxSize = 2 * textRadius;
|
||||
|
|
|
@ -116,20 +116,19 @@
|
|||
app:layout_constraintStart_toEndOf="@+id/nav_speed_limit"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/street_frame"
|
||||
app:activeLaneTintColor="?navLaneArrowActiveColor"
|
||||
app:inactiveLaneTintColor="?navLaneArrowInactiveColor"
|
||||
app:backgroundColor="?colorAccent"
|
||||
app:cornerRadius="@dimen/margin_quarter"
|
||||
app:editModeLanesCount="10"
|
||||
app:lanesActiveLaneTintColor="?navLaneArrowActiveColor"
|
||||
app:lanesInactiveLaneTintColor="?navLaneArrowInactiveColor"
|
||||
app:lanesBackgroundColor="?colorAccent"
|
||||
app:lanesCornerRadius="@dimen/margin_quarter"
|
||||
app:lanesEditModeLanesCount="10"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<app.organicmaps.widget.SpeedLimitView
|
||||
android:id="@+id/nav_speed_limit"
|
||||
style="@style/MwmWidget.SpeedLimit"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_margin="@dimen/margin_half"
|
||||
app:editModeCurrentSpeed="90"
|
||||
app:editModeSpeedLimit="120"
|
||||
app:layout_constraintStart_toEndOf="@id/nav_next_turn_container"
|
||||
app:layout_constraintTop_toBottomOf="@id/street_frame" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -117,20 +117,19 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/nav_next_turn_container"
|
||||
app:layout_constraintTop_toBottomOf="@id/street_frame"
|
||||
app:activeLaneTintColor="?navLaneArrowActiveColor"
|
||||
app:inactiveLaneTintColor="?navLaneArrowInactiveColor"
|
||||
app:backgroundColor="?navLanesBackgroundColor"
|
||||
app:cornerRadius="@dimen/margin_quarter"
|
||||
app:editModeLanesCount="5"
|
||||
app:lanesActiveLaneTintColor="?navLaneArrowActiveColor"
|
||||
app:lanesInactiveLaneTintColor="?navLaneArrowInactiveColor"
|
||||
app:lanesBackgroundColor="?navLanesBackgroundColor"
|
||||
app:lanesCornerRadius="@dimen/margin_quarter"
|
||||
app:lanesEditModeLanesCount="5"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<app.organicmaps.widget.SpeedLimitView
|
||||
android:id="@+id/nav_speed_limit"
|
||||
style="@style/MwmWidget.SpeedLimit"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_margin="@dimen/margin_half"
|
||||
app:editModeCurrentSpeed="90"
|
||||
app:editModeSpeedLimit="120"
|
||||
app:layout_constraintEnd_toEndOf="@id/nav_next_turn_container"
|
||||
app:layout_constraintStart_toStartOf="@id/nav_next_turn_container"
|
||||
app:layout_constraintTop_toBottomOf="@id/nav_next_turn_container" />
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="SpeedLimitView">
|
||||
<attr name="BackgroundColor" format="color" />
|
||||
<attr name="borderColor" format="color" />
|
||||
<attr name="alertColor" format="color" />
|
||||
<attr name="textColor" format="color" />
|
||||
<attr name="textAlertColor" format="color" />
|
||||
<attr name="speedLimitBackgroundColor" format="color" />
|
||||
<attr name="speedLimitBorderColor" format="color" />
|
||||
<attr name="speedLimitAlertColor" format="color" />
|
||||
<attr name="speedLimitTextColor" format="color" />
|
||||
<attr name="speedLimitTextAlertColor" format="color" />
|
||||
<!-- These values are used only in edit mode -->
|
||||
<attr name="editModeSpeedLimit" format="integer" />
|
||||
<attr name="editModeCurrentSpeed" format="integer" />
|
||||
<attr name="speedLimitEditModeSpeedLimit" format="integer" />
|
||||
<attr name="speedLimitEditModeAlert" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="LanesView">
|
||||
<attr name="activeLaneTintColor" format="reference" />
|
||||
<attr name="inactiveLaneTintColor" format="color" />
|
||||
<attr name="backgroundColor" format="color" />
|
||||
<attr name="cornerRadius" format="dimension" />
|
||||
<attr name="lanesActiveLaneTintColor" format="reference" />
|
||||
<attr name="lanesInactiveLaneTintColor" format="color" />
|
||||
<attr name="lanesBackgroundColor" format="color" />
|
||||
<attr name="lanesCornerRadius" format="dimension" />
|
||||
<!-- These values are used only in edit mode -->
|
||||
<attr name="editModeLanesCount" format="integer" />
|
||||
<attr name="lanesEditModeLanesCount" format="integer" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="WheelProgressView">
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
<style name="MwmWidget.ProgressWheel"/>
|
||||
|
||||
<style name="MwmWidget.SpeedLimit">
|
||||
<item name="speedLimitAlertColor">@color/base_red</item>
|
||||
<item name="speedLimitBorderColor">@color/base_red</item>
|
||||
</style>
|
||||
|
||||
<style name="MwmWidget.FrameLayout"/>
|
||||
|
||||
<style name="MwmWidget.Downloader"/>
|
||||
|
|
|
@ -199,11 +199,14 @@ double MpsToUnits(double metersPerSecond, Units units)
|
|||
UNREACHABLE();
|
||||
}
|
||||
|
||||
int FormatSpeed(double metersPerSecond, Units units)
|
||||
{
|
||||
return static_cast<int>(std::round(MpsToUnits(metersPerSecond, units)));
|
||||
}
|
||||
|
||||
std::string FormatSpeedNumeric(double metersPerSecond, Units units)
|
||||
{
|
||||
double const unitsPerHour = MpsToUnits(metersPerSecond, units);
|
||||
double roundedValue = std::round(unitsPerHour);
|
||||
return std::to_string(static_cast<int>(roundedValue));
|
||||
return std::to_string(FormatSpeed(metersPerSecond, units));
|
||||
}
|
||||
|
||||
std::string FormatOsmLink(double lat, double lon, int zoom)
|
||||
|
|
|
@ -33,6 +33,8 @@ inline double constexpr KmphToMps(double kmph) { return kmph * 1000 / 3600; }
|
|||
double ToSpeedKmPH(double speed, Units units);
|
||||
double MpsToUnits(double mps, Units units);
|
||||
|
||||
/// @return Speed value in km/h for Metric and in mph for Imperial.
|
||||
int FormatSpeed(double metersPerSecond, Units units);
|
||||
/// @return Speed value string (without suffix) in km/h for Metric and in mph for Imperial.
|
||||
std::string FormatSpeedNumeric(double metersPerSecond, Units units);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue