[android] Add current speed widget

Signed-off-by: TobiPeterG <codeberg.sadness522@passmail.net>
This commit is contained in:
TobiPeterG
2025-08-04 23:38:43 +02:00
committed by Harry Bond
parent 4bad37a829
commit ea1d0eefa2
8 changed files with 392 additions and 189 deletions

View File

@@ -26,6 +26,7 @@ import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils;
import app.organicmaps.widget.CurrentSpeedView;
import app.organicmaps.widget.LanesView;
import app.organicmaps.widget.SpeedLimitView;
import app.organicmaps.widget.menu.NavMenu;
@@ -51,6 +52,8 @@ public class NavigationController implements TrafficManager.TrafficCallback, Nav
private final LanesView mLanesView;
@NonNull
private final SpeedLimitView mSpeedLimit;
@NonNull
private final CurrentSpeedView mCurrentSpeed;
private final MapButtonsViewModel mMapButtonsViewModel;
@@ -94,6 +97,7 @@ public class NavigationController implements TrafficManager.TrafficCallback, Nav
mLanesView = topFrame.findViewById(R.id.lanes);
mSpeedLimit = topFrame.findViewById(R.id.nav_speed_limit);
mCurrentSpeed = topFrame.findViewById(R.id.nav_current_speed);
// Show a blank view below the navbar to hide the menu content
final View navigationBarBackground = mFrame.findViewById(R.id.nav_bottom_sheet_nav_bar);
@@ -128,7 +132,7 @@ public class NavigationController implements TrafficManager.TrafficCallback, Nav
mLanesView.setLanes(info.lanes);
updateSpeedLimit(info);
updateSpeedWidgets(info);
}
private void updatePedestrian(@NonNull RoutingInfo info)
@@ -136,6 +140,7 @@ public class NavigationController implements TrafficManager.TrafficCallback, Nav
mNextTurnDistance.setText(Utils.formatDistance(mFrame.getContext(), info.distToTurn));
info.pedestrianTurnDirection.setTurnDrawable(mNextTurnImage);
updateSpeedWidgets(info);
}
public void updateNorth()
@@ -261,16 +266,18 @@ public class NavigationController implements TrafficManager.TrafficCallback, Nav
RoutingController.get().cancel();
}
private void updateSpeedLimit(@NonNull final RoutingInfo info)
private void updateSpeedWidgets(@NonNull final RoutingInfo info)
{
final Location location = MwmApplication.from(mFrame.getContext()).getLocationHelper().getSavedLocation();
if (location == null)
{
mSpeedLimit.setSpeedLimit(0, false);
mSpeedLimit.setSpeedLimit(-1, false);
mCurrentSpeed.setCurrentSpeed(-1);
return;
}
final int fSpeedLimit = StringUtils.nativeFormatSpeed(info.speedLimitMps);
final boolean speedLimitExceeded = fSpeedLimit < StringUtils.nativeFormatSpeed(location.getSpeed());
mSpeedLimit.setSpeedLimit(fSpeedLimit, speedLimitExceeded);
mCurrentSpeed.setCurrentSpeed(location.getSpeed());
}
}

View File

@@ -0,0 +1,170 @@
package app.organicmaps.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public abstract class BaseSignView extends View
{
private float mBorderWidthRatio = 0.1f;
protected void setBorderWidthRatio(float ratio) {
mBorderWidthRatio = ratio;
}
private float mBorderInsetRatio = 0f;
protected void setBorderInsetRatio(float ratio) {
mBorderInsetRatio = ratio;
}
// colors
protected int mBackgroundColor;
protected int mBorderColor;
protected int mAlertColor;
protected int mTextColor;
protected int mTextAlertColor;
// paints
protected final Paint mBackgroundPaint;
protected final Paint mBorderPaint;
protected final Paint mTextPaint;
// geometry
protected float mWidth;
protected float mHeight;
protected float mRadius;
protected float mBorderWidth;
protected float mBorderRadius;
public BaseSignView(Context ctx, @Nullable AttributeSet attrs)
{
super(ctx, attrs);
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBorderPaint.setStyle(Paint.Style.STROKE);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
}
protected void setColors(int backgroundColor,
int borderColor,
int alertColor,
int textColor,
int textAlertColor)
{
mBackgroundColor = backgroundColor;
mBorderColor = borderColor;
mAlertColor = alertColor;
mTextColor = textColor;
mTextAlertColor = textAlertColor;
mBackgroundPaint.setColor(mBackgroundColor);
mBorderPaint.setColor(mBorderColor);
mTextPaint.setColor(mTextColor);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
float px = getPaddingLeft() + getPaddingRight();
float py = getPaddingTop() + getPaddingBottom();
mWidth = w - px;
mHeight = h - py;
mRadius = Math.min(mWidth, mHeight) / 2f;
mBorderWidth = mRadius * mBorderWidthRatio;
// subtract half the stroke PLUS the extra inset
float gap = mRadius * mBorderInsetRatio;
mBorderRadius = mRadius - (mBorderWidth / 2f) - gap;
configureTextSize();
}
@Override
protected void onDraw(@NonNull Canvas canvas)
{
super.onDraw(canvas);
String str = getValueString();
if (str == null) return;
float cx = mWidth / 2f;
float cy = mHeight / 2f;
// background & border
boolean alert = isAlert();
mBackgroundPaint.setColor(alert ? mAlertColor : mBackgroundColor);
canvas.drawCircle(cx, cy, mRadius, mBackgroundPaint);
if (!alert)
{
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderPaint.setColor(mBorderColor);
canvas.drawCircle(cx, cy, mBorderRadius, mBorderPaint);
}
// text
mTextPaint.setColor(alert ? mTextAlertColor : mTextColor);
drawValueString(canvas, cx, cy, str);
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent e)
{
float cx = mWidth / 2f, cy = mHeight / 2f;
float dx = e.getX() - cx, dy = e.getY() - cy;
if (dx*dx + dy*dy <= mRadius*mRadius)
{
performClick();
return true;
}
return false;
}
@Override
public boolean performClick()
{
super.performClick();
return false;
}
private void drawValueString(Canvas c, float cx, float cy, String str)
{
Rect b = new Rect();
mTextPaint.getTextBounds(str, 0, str.length(), b);
float y = cy - b.exactCenterY();
c.drawText(str, cx, y, mTextPaint);
}
void configureTextSize()
{
String text = getValueString();
if (text == null) return;
float textRadius = mBorderRadius - mBorderWidth;
float maxSz = 2f * textRadius;
float maxSz2 = maxSz * maxSz;
float lo = 0f, hi = maxSz, sz = maxSz;
Rect b = new Rect();
while (lo <= hi)
{
sz = (lo + hi) / 2f;
mTextPaint.setTextSize(sz);
mTextPaint.getTextBounds(text, 0, text.length(), b);
float area = b.width()*b.width() + b.height()*b.height();
if (area <= maxSz2) lo = sz + 1f;
else hi = sz - 1f;
}
mTextPaint.setTextSize(Math.max(1f, sz));
}
/** child must return the string to draw, or null if nothing */
@Nullable
protected abstract String getValueString();
/** child decides if this is in “alert” state */
protected abstract boolean isAlert();
}

View File

@@ -0,0 +1,77 @@
package app.organicmaps.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Pair;
import androidx.annotation.Nullable;
import app.organicmaps.R;
import app.organicmaps.sdk.util.StringUtils;
public class CurrentSpeedView extends BaseSignView
{
private double mSpeedMps = -1.0;
private String mSpeedStr = "--";
public CurrentSpeedView(Context ctx, @Nullable AttributeSet attrs)
{
super(ctx, attrs);
setBorderWidthRatio(0.1f);
setBorderInsetRatio(0.05f);
try (TypedArray a = ctx.getTheme()
.obtainStyledAttributes(attrs, R.styleable.CurrentSpeedView /* reuse same attrs or define new */ , 0, 0))
{
int bg = a.getColor(R.styleable.CurrentSpeedView_currentSpeedBackgroundColor, DefaultValues.BACKGROUND_COLOR);
int bd = a.getColor(R.styleable.CurrentSpeedView_currentSpeedBorderColor, DefaultValues.BORDER_COLOR);
int tc = a.getColor(R.styleable.CurrentSpeedView_currentSpeedTextColor, DefaultValues.TEXT_COLOR);
setColors(bg, bd, 0, tc, 0);
if (isInEditMode())
{
mSpeedMps = a.getInt(R.styleable.CurrentSpeedView_currentSpeedEditModeCurrentSpeed, 50);
mSpeedStr = Integer.toString((int)mSpeedMps);
}
}
}
public void setCurrentSpeed(double mps)
{
mSpeedMps = mps;
if (mps < 0)
{
mSpeedStr = "--";
}
else
{
Pair<String,String> su = StringUtils.nativeFormatSpeedAndUnits(mps);
mSpeedStr = su.first;
}
requestLayout();
configureTextSize();
invalidate();
}
@Nullable
@Override
protected String getValueString()
{
return mSpeedStr;
}
@Override
protected boolean isAlert()
{
return false;
}
private interface DefaultValues
{
int BACKGROUND_COLOR = 0xFFFFFFFF;
int BORDER_COLOR = 0xFF000000;
int TEXT_COLOR = 0xFF000000;
}
}

View File

@@ -3,225 +3,135 @@ package app.organicmaps.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.organicmaps.R;
public class SpeedLimitView extends View
public class SpeedLimitView extends BaseSignView
{
private interface DefaultValues
private int mSpeedLimit = -1;
private boolean mAlert = false;
private String mSpeedStr = "-1";
private final int unlimitedBorderColor;
private final int unlimitedStripeColor;
public SpeedLimitView(Context ctx, @Nullable AttributeSet attrs)
{
@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;
super(ctx, attrs);
float BORDER_WIDTH_RATIO = 0.1f;
}
setBorderWidthRatio(0.2f);
setBorderInsetRatio(0.05f);
@ColorInt
private final int mBackgroundColor;
@ColorInt
private final int mBorderColor;
@ColorInt
private final int mAlertColor;
@ColorInt
private final int mTextColor;
@ColorInt
private final int mTextAlertColor;
@NonNull
private final Paint mSignBackgroundPaint;
@NonNull
private final Paint mSignBorderPaint;
@NonNull
private final Paint mTextPaint;
private float mWidth;
private float mHeight;
private float mBackgroundRadius;
private float mBorderRadius;
private float mBorderWidth;
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))
try (TypedArray a = ctx.getTheme()
.obtainStyledAttributes(attrs, R.styleable.SpeedLimitView, 0, 0))
{
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);
int bg = a.getColor(R.styleable.SpeedLimitView_speedLimitBackgroundColor, DefaultValues.BACKGROUND_COLOR);
int bd = a.getColor(R.styleable.SpeedLimitView_speedLimitBorderColor, DefaultValues.BORDER_COLOR);
int al = a.getColor(R.styleable.SpeedLimitView_speedLimitAlertColor, DefaultValues.ALERT_COLOR);
int tc = a.getColor(R.styleable.SpeedLimitView_speedLimitTextColor, DefaultValues.TEXT_COLOR);
int tac = a.getColor(R.styleable.SpeedLimitView_speedLimitTextAlertColor, DefaultValues.TEXT_ALERT_COLOR);
setColors(bg, bd, al, tc, tac);
unlimitedBorderColor = a.getColor(R.styleable.SpeedLimitView_speedLimitUnlimitedBorderColor, DefaultValues.UNLIMITED_BORDER_COLOR);
unlimitedStripeColor = a.getColor(R.styleable.SpeedLimitView_speedLimitUnlimitedStripeColor, DefaultValues.UNLIMITED_STRIPE_COLOR);
if (isInEditMode())
{
mSpeedLimit = data.getInt(R.styleable.SpeedLimitView_speedLimitEditModeSpeedLimit, 60);
mSpeedLimitStr = Integer.toString(mSpeedLimit);
mAlert = data.getBoolean(R.styleable.SpeedLimitView_speedLimitEditModeAlert, false);
mSpeedLimit = a.getInt(R.styleable.SpeedLimitView_speedLimitEditModeSpeedLimit, 60);
mAlert = a.getBoolean(R.styleable.SpeedLimitView_speedLimitEditModeAlert, false);
mSpeedStr = Integer.toString(mSpeedLimit);
}
}
mSignBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mSignBackgroundPaint.setColor(mBackgroundColor);
mSignBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mSignBorderPaint.setColor(mBorderColor);
mSignBorderPaint.setStrokeWidth(mBorderWidth);
mSignBorderPaint.setStyle(Paint.Style.STROKE);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(mTextColor);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
}
public void setSpeedLimit(final int speedLimit, boolean alert)
public void setSpeedLimit(int limit, boolean alert)
{
final boolean speedLimitChanged = mSpeedLimit != speedLimit;
mSpeedLimit = speedLimit;
mAlert = alert;
if (speedLimitChanged)
if (mSpeedLimit != limit)
{
mSpeedLimitStr = Integer.toString(mSpeedLimit);
configureTextSize();
mSpeedLimit = limit;
mSpeedStr = Integer.toString(limit);
requestLayout();
}
mAlert = alert;
configureTextSize();
invalidate();
}
@Nullable
@Override
protected void onDraw(@NonNull Canvas canvas)
protected String getValueString()
{
super.onDraw(canvas);
final boolean validSpeedLimit = mSpeedLimit > 0;
if (!validSpeedLimit)
return;
final float cx = mWidth / 2;
final float cy = mHeight / 2;
drawSign(canvas, cx, cy, mAlert);
drawText(canvas, cx, cy, mAlert);
return (mSpeedLimit > 0 ? mSpeedStr : null);
}
private void drawSign(@NonNull Canvas canvas, float cx, float cy, boolean alert)
@Override
protected boolean isAlert()
{
if (alert)
mSignBackgroundPaint.setColor(mAlertColor);
return mAlert;
}
@Override
protected void onDraw(Canvas canvas)
{
float cx = mWidth/2f, cy = mHeight/2f;
if (mSpeedLimit == 0)
{
// background
mBackgroundPaint.setColor(mBackgroundColor);
canvas.drawCircle(cx, cy, mRadius, mBackgroundPaint);
// black border
mBorderPaint.setColor(unlimitedBorderColor);
mBorderPaint.setStrokeWidth(mBorderWidth);
canvas.drawCircle(cx, cy, mBorderRadius, mBorderPaint);
// draw 5 diagonal stripes
drawUnlimitedStripes(canvas, cx, cy);
}
else
mSignBackgroundPaint.setColor(mBackgroundColor);
canvas.drawCircle(cx, cy, mBackgroundRadius, mSignBackgroundPaint);
if (!alert)
{
mSignBorderPaint.setStrokeWidth(mBorderWidth);
canvas.drawCircle(cx, cy, mBorderRadius, mSignBorderPaint);
// delegate to BaseSignViews onDraw
super.onDraw(canvas);
}
}
private void drawText(@NonNull Canvas canvas, float cx, float cy, boolean alert)
private void drawUnlimitedStripes(Canvas c, float cx, float cy)
{
if (alert)
mTextPaint.setColor(mTextAlertColor);
else
mTextPaint.setColor(mTextColor);
Paint stripe = new Paint(Paint.ANTI_ALIAS_FLAG);
stripe.setColor(unlimitedStripeColor);
stripe.setStrokeWidth(mBorderWidth * 0.4f);
final Rect textBounds = new Rect();
mTextPaint.getTextBounds(mSpeedLimitStr, 0, mSpeedLimitStr.length(), textBounds);
final float textY = cy - textBounds.exactCenterY();
canvas.drawText(mSpeedLimitStr, cx, textY, mTextPaint);
}
float r = mRadius * 0.8f; // shorten to 80% of full radius
float diag = (float)(1/Math.sqrt(2));
float dx = -diag, dy = +diag;
float px = -dy, py = +dx; // perpendicular
float step = r * 0.15f; // spacing
@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))
for (int i = -2; i <= 2; i++)
{
performClick();
return true;
float ox = px * step * i;
float oy = py * step * i;
float sx = cx + dx * r + ox;
float sy = cy + dy * r + oy;
float ex = cx - dx * r + ox;
float ey = cy - dy * r + oy;
c.drawLine(sx, sy, ex, ey, stripe);
}
return false;
}
@Override
public boolean performClick()
private interface DefaultValues
{
super.performClick();
return false;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
final float paddingX = (float) (getPaddingLeft() + getPaddingRight());
final float paddingY = (float) (getPaddingTop() + getPaddingBottom());
mWidth = (float) w - paddingX;
mHeight = (float) h - paddingY;
mBackgroundRadius = Math.min(mWidth, mHeight) / 2;
mBorderWidth = mBackgroundRadius * 2 * DefaultValues.BORDER_WIDTH_RATIO;
mBorderRadius = mBackgroundRadius - mBorderWidth / 2;
configureTextSize();
}
// Apply binary search to determine the optimal text size that fits within the circular boundary.
private void configureTextSize()
{
final String text = mSpeedLimitStr;
final float textRadius = mBorderRadius - mBorderWidth;
final float textMaxSize = 2 * textRadius;
final float textMaxSizeSquared = (float) Math.pow(textMaxSize, 2);
float lowerBound = 0;
float upperBound = textMaxSize;
float textSize = textMaxSize;
final Rect textBounds = new Rect();
while (lowerBound <= upperBound)
{
textSize = (lowerBound + upperBound) / 2;
mTextPaint.setTextSize(textSize);
mTextPaint.getTextBounds(text, 0, text.length(), textBounds);
if (Math.pow(textBounds.width(), 2) + Math.pow(textBounds.height(), 2) <= textMaxSizeSquared)
lowerBound = textSize + 1;
else
upperBound = textSize - 1;
}
mTextPaint.setTextSize(Math.max(1, textSize));
int BACKGROUND_COLOR = 0xFFFFFFFF;
int BORDER_COLOR = 0xFFFF0000;
int ALERT_COLOR = 0xFFFF0000;
int TEXT_COLOR = 0xFF000000;
int TEXT_ALERT_COLOR = 0xFFFFFFFF;
int UNLIMITED_BORDER_COLOR = 0xFF000000;
int UNLIMITED_STRIPE_COLOR = 0xFF000000;
}
}

View File

@@ -123,12 +123,24 @@
app:lanesEditModeLanesCount="10"
tools:visibility="visible" />
<app.organicmaps.widget.CurrentSpeedView
android:id="@+id/nav_current_speed"
style="@style/MwmWidget.CurrentSpeed"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_margin="@dimen/margin_half"
app:layout_constraintStart_toEndOf="@id/nav_next_turn_container"
app:layout_constraintTop_toBottomOf="@id/street_frame"/>
<app.organicmaps.widget.SpeedLimitView
android:id="@+id/nav_speed_limit"
style="@style/MwmWidget.SpeedLimit"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_margin="@dimen/margin_half"
app:layout_constraintStart_toEndOf="@id/nav_next_turn_container"
app:layout_constraintTop_toBottomOf="@id/street_frame" />
app:layout_constraintTop_toBottomOf="@id/nav_current_speed"
android:translationY="-21dp"
android:translationX="-12dp"
android:translationZ="1dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -124,13 +124,26 @@
app:lanesEditModeLanesCount="5"
tools:visibility="visible" />
<app.organicmaps.widget.CurrentSpeedView
android:id="@+id/nav_current_speed"
style="@style/MwmWidget.CurrentSpeed"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_margin="@dimen/margin_half"
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"/>
<app.organicmaps.widget.SpeedLimitView
android:id="@+id/nav_speed_limit"
style="@style/MwmWidget.SpeedLimit"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_margin="@dimen/margin_half"
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" />
app:layout_constraintTop_toBottomOf="@id/nav_current_speed"
android:translationY="-23dp"
android:translationX="-23dp"
android:translationZ="1dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -3,6 +3,8 @@
<declare-styleable name="SpeedLimitView">
<attr name="speedLimitBackgroundColor" format="color" />
<attr name="speedLimitBorderColor" format="color" />
<attr name="speedLimitUnlimitedBorderColor" format="color" />
<attr name="speedLimitUnlimitedStripeColor" format="color" />
<attr name="speedLimitAlertColor" format="color" />
<attr name="speedLimitTextColor" format="color" />
<attr name="speedLimitTextAlertColor" format="color" />
@@ -11,6 +13,14 @@
<attr name="speedLimitEditModeAlert" format="boolean" />
</declare-styleable>
<declare-styleable name="CurrentSpeedView">
<attr name="currentSpeedBackgroundColor" format="color" />
<attr name="currentSpeedBorderColor" format="color" />
<attr name="currentSpeedTextColor" format="color" />
<!-- These values are used only in edit mode -->
<attr name="currentSpeedEditModeCurrentSpeed" format="integer" />
</declare-styleable>
<declare-styleable name="LanesView">
<attr name="lanesActiveLaneTintColor" format="reference" />
<attr name="lanesInactiveLaneTintColor" format="color" />

View File

@@ -10,6 +10,10 @@
<item name="speedLimitBorderColor">@color/base_red</item>
</style>
<style name="MwmWidget.CurrentSpeed">
<item name="speedLimitBorderColor">@color/black_primary</item>
</style>
<style name="MwmWidget.FrameLayout"/>
<style name="MwmWidget.Downloader"/>