Implement widget for the current speed #9738
14 changed files with 501 additions and 252 deletions
0
android/app/.attach_pid35553
Normal file
0
android/app/.attach_pid35553
Normal file
|
@ -249,7 +249,7 @@ public class NavigationController implements TrafficManager.TrafficCallback,
|
|||
{
|
||||
final Location location = LocationHelper.from(mFrame.getContext()).getSavedLocation();
|
||||
if (location == null) {
|
||||
mSpeedLimit.setSpeedLimitMps(0);
|
||||
mSpeedLimit.setSpeedLimitMps(-1);
|
||||
return;
|
||||
}
|
||||
mSpeedLimit.setCurrentSpeed(location.getSpeed());
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
package app.organicmaps.widget;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
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.RectF;
|
||||
import android.graphics.Typeface;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import app.organicmaps.Framework;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.util.StringUtils;
|
||||
|
||||
|
@ -28,17 +35,27 @@ public class SpeedLimitView extends View
|
|||
@ColorInt
|
||||
int TEXT_COLOR = Color.BLACK;
|
||||
@ColorInt
|
||||
int UNLIMITED_BORDER_COLOR = Color.BLACK;
|
||||
@ColorInt
|
||||
int TEXT_ALERT_COLOR = Color.WHITE;
|
||||
|
||||
float BORDER_WIDTH_RATIO = 0.1f;
|
||||
float BORDER_WIDTH_RATIO = 0.2f;
|
||||
|
||||
float BORDER_RADIUS_RATIO = 0.95f;
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
private final int mBackgroundColor;
|
||||
|
||||
@ColorInt
|
||||
private final int mBackgroundColorWidget;
|
||||
|
||||
@ColorInt
|
||||
private final int mBorderColor;
|
||||
|
||||
@ColorInt
|
||||
private final int mUnlimitedBorderColor;
|
||||
|
||||
@ColorInt
|
||||
private final int mAlertColor;
|
||||
|
||||
|
@ -53,7 +70,23 @@ public class SpeedLimitView extends View
|
|||
@NonNull
|
||||
private final Paint mSignBorderPaint;
|
||||
@NonNull
|
||||
private final Paint mSignUnlimitedBorderPaint;
|
||||
@NonNull
|
||||
private final Paint mTextPaint;
|
||||
@NonNull
|
||||
private final Paint mCurrentSpeedBorderPaint;
|
||||
@NonNull
|
||||
private final Paint mCurrentSpeedBackgroundPaint;
|
||||
@NonNull
|
||||
private final Paint mCurrentSpeedTextPaint;
|
||||
@NonNull
|
||||
private final Paint mCurrentSpeedUnitsTextPaint; // Added for units text
|
||||
@NonNull
|
||||
private final Paint mBackgroundPaint;
|
||||
@NonNull
|
||||
private final Paint mWidgetBackgroundPaint;
|
||||
private float mSpeedLimitAlpha;
|
||||
|
||||
|
||||
private float mWidth;
|
||||
private float mHeight;
|
||||
|
@ -64,18 +97,37 @@ public class SpeedLimitView extends View
|
|||
private double mSpeedLimitMps;
|
||||
@Nullable
|
||||
private String mSpeedLimitStr;
|
||||
@Nullable
|
||||
private String mCurrentSpeedStr;
|
||||
@Nullable
|
||||
private String mCurrentSpeedUnitsStr;
|
||||
|
||||
private double mCurrentSpeed;
|
||||
private double mCurrentSpeedMps;
|
||||
|
||||
/**
|
||||
* We’ll store the bottom system navigation bar (or gesture bar) inset here.
|
||||
* Instead of subtracting it from the height, we’ll apply a vertical translation
|
||||
* so the entire widget moves up.
|
||||
*/
|
||||
private int mBottomSystemWindowInset = 0;
|
||||
private int mLeftSystemWindowInset = 0;
|
||||
|
||||
@SuppressLint("SwitchIntDef")
|
||||
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))
|
||||
{
|
||||
mBackgroundColorWidget = data.getColor(R.styleable.SpeedLimitView_WidgetBackgroundColor, switch (Framework.nativeGetMapStyle()) {
|
||||
case Framework.MAP_STYLE_DARK, Framework.MAP_STYLE_VEHICLE_DARK, Framework.MAP_STYLE_OUTDOORS_DARK ->
|
||||
Color.DKGRAY;
|
||||
default -> Color.WHITE;
|
||||
});
|
||||
mBackgroundColor = data.getColor(R.styleable.SpeedLimitView_BackgroundColor, DefaultValues.BACKGROUND_COLOR);
|
||||
mBorderColor = data.getColor(R.styleable.SpeedLimitView_borderColor, ContextCompat.getColor(context, R.color.base_red));
|
||||
mUnlimitedBorderColor = data.getColor(R.styleable.SpeedLimitView_unlimitedBorderColor, DefaultValues.UNLIMITED_BORDER_COLOR);
|
||||
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);
|
||||
|
@ -83,7 +135,8 @@ public class SpeedLimitView extends View
|
|||
{
|
||||
mSpeedLimitMps = data.getInt(R.styleable.SpeedLimitView_editModeSpeedLimit, -1);
|
||||
mSpeedLimitStr = mSpeedLimitMps > 0 ? String.valueOf(((int) mSpeedLimitMps)) : null;
|
||||
mCurrentSpeed = data.getInt(R.styleable.SpeedLimitView_editModeCurrentSpeed, -1);
|
||||
mCurrentSpeedMps = data.getInt(R.styleable.SpeedLimitView_editModeCurrentSpeed, -1);
|
||||
mCurrentSpeedStr = mCurrentSpeedMps > 0 ? String.valueOf(((int) mCurrentSpeedMps)) : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,11 +147,49 @@ public class SpeedLimitView extends View
|
|||
mSignBorderPaint.setColor(mBorderColor);
|
||||
mSignBorderPaint.setStrokeWidth(mBorderWidth);
|
||||
mSignBorderPaint.setStyle(Paint.Style.STROKE);
|
||||
mSignUnlimitedBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mSignUnlimitedBorderPaint.setColor(mUnlimitedBorderColor);
|
||||
mSignUnlimitedBorderPaint.setStrokeWidth(mBorderWidth);
|
||||
mSignUnlimitedBorderPaint.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));
|
||||
|
||||
mCurrentSpeedBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mCurrentSpeedBackgroundPaint.setColor(mBackgroundColor);
|
||||
mCurrentSpeedTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mCurrentSpeedTextPaint.setColor(mTextColor);
|
||||
mCurrentSpeedTextPaint.setTextAlign(Paint.Align.CENTER);
|
||||
mCurrentSpeedTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
|
||||
mCurrentSpeedUnitsTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mCurrentSpeedUnitsTextPaint.setColor(mTextColor);
|
||||
mCurrentSpeedUnitsTextPaint.setTextAlign(Paint.Align.CENTER);
|
||||
mCurrentSpeedUnitsTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
|
||||
mCurrentSpeedBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mCurrentSpeedBorderPaint.setColor(Color.BLACK);
|
||||
mCurrentSpeedBorderPaint.setStyle(Paint.Style.STROKE);
|
||||
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mBackgroundPaint.setColor(mBackgroundColor);
|
||||
mWidgetBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mWidgetBackgroundPaint.setColor(mBackgroundColorWidget);
|
||||
mSpeedLimitMps = -1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture bottom navigation bar insets (gesture area).
|
||||
* We’ll use this to translate the canvas up.
|
||||
*/
|
||||
@Override
|
||||
@NonNull
|
||||
public WindowInsets onApplyWindowInsets(@NonNull WindowInsets insets)
|
||||
{
|
||||
mBottomSystemWindowInset = insets.getSystemWindowInsetBottom();
|
||||
mLeftSystemWindowInset = insets.getSystemWindowInsetLeft();
|
||||
// Request a re-draw so we can apply the translation in onDraw().
|
||||
invalidate();
|
||||
return super.onApplyWindowInsets(insets);
|
||||
}
|
||||
|
||||
public void setSpeedLimitMps(final double speedLimitMps)
|
||||
|
@ -106,65 +197,192 @@ public class SpeedLimitView extends View
|
|||
if (mSpeedLimitMps == speedLimitMps)
|
||||
return;
|
||||
|
||||
boolean hadSpeedLimit = mSpeedLimitMps >= 0;
|
||||
mSpeedLimitMps = speedLimitMps;
|
||||
if (mSpeedLimitMps <= 0)
|
||||
{
|
||||
mSpeedLimitStr = null;
|
||||
setVisibility(GONE);
|
||||
return;
|
||||
boolean hasSpeedLimit = mSpeedLimitMps >= 0;
|
||||
|
||||
if (mSpeedLimitMps >= 0) {
|
||||
final Pair<String, String> speedLimitAndUnits = StringUtils.nativeFormatSpeedAndUnits(mSpeedLimitMps);
|
||||
mSpeedLimitStr = speedLimitAndUnits.first;
|
||||
}
|
||||
|
||||
final Pair<String, String> speedLimitAndUnits = StringUtils.nativeFormatSpeedAndUnits(mSpeedLimitMps);
|
||||
setVisibility(VISIBLE);
|
||||
mSpeedLimitStr = speedLimitAndUnits.first;
|
||||
if (hadSpeedLimit != hasSpeedLimit) {
|
||||
animateSpeedLimitAlpha(hasSpeedLimit);
|
||||
} else {
|
||||
invalidate();
|
||||
}
|
||||
configureTextSize();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setCurrentSpeed(final double currentSpeed)
|
||||
{
|
||||
mCurrentSpeed = currentSpeed;
|
||||
private void animateSpeedLimitAlpha(final boolean fadeIn) {
|
||||
float startAlpha = fadeIn ? 0f : 1f;
|
||||
float endAlpha = fadeIn ? 1f : 0f;
|
||||
ValueAnimator animator = ValueAnimator.ofFloat(startAlpha, endAlpha);
|
||||
animator.setDuration(500);
|
||||
animator.addUpdateListener(animation -> {
|
||||
mSpeedLimitAlpha = (float) animation.getAnimatedValue();
|
||||
invalidate();
|
||||
});
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (!fadeIn) {
|
||||
mSpeedLimitStr = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
animator.start();
|
||||
}
|
||||
public void setCurrentSpeed(final double currentSpeedMps) {
|
||||
mCurrentSpeedMps = currentSpeedMps;
|
||||
final Pair<String, String> speedAndUnits = StringUtils.nativeFormatSpeedAndUnits(mCurrentSpeedMps);
|
||||
if (mCurrentSpeedMps < 0)
|
||||
mCurrentSpeedStr = "0";
|
||||
else
|
||||
mCurrentSpeedStr = speedAndUnits.first;
|
||||
mCurrentSpeedUnitsStr = speedAndUnits.second;
|
||||
configureTextSize();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(@NonNull Canvas canvas)
|
||||
{
|
||||
super.onDraw(canvas);
|
||||
private void draw_widgets(@NonNull Canvas canvas, float cx, float cx_or_cy, float cy, boolean isLandscape) {
|
||||
final boolean alert = mSpeedLimitMps > 0 && mSpeedLimitStr != null && Integer.parseInt(mCurrentSpeedStr) > Integer.parseInt(mSpeedLimitStr); //TODO do better?
|
||||
float second_cx = (isLandscape) ? cx_or_cy : cx;
|
||||
float second_cy = (isLandscape) ? cy : cx_or_cy;
|
||||
// Draw combined background and speed limit sign with layer alpha
|
||||
if (mSpeedLimitAlpha > 0f) {
|
||||
int saveCount = canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), (int) (mSpeedLimitAlpha * 255));
|
||||
drawCombinedBackground(canvas, cx, cx_or_cy, cy);
|
||||
// Draw speed limit sign and text
|
||||
if (mSpeedLimitStr != null)
|
||||
drawSpeedLimitSign(canvas, cx, second_cy);
|
||||
|
||||
final boolean alert = mCurrentSpeed > mSpeedLimitMps && mSpeedLimitMps > 0;
|
||||
|
||||
final float cx = mWidth / 2;
|
||||
final float cy = mHeight / 2;
|
||||
|
||||
drawSign(canvas, cx, cy, alert);
|
||||
drawText(canvas, cx, cy, alert);
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
// Draw current speed sign and text (always visible)
|
||||
if (mCurrentSpeedStr != null)
|
||||
drawCurrentSpeedSign(canvas, second_cx, cy, alert);
|
||||
}
|
||||
|
||||
private void drawSign(@NonNull Canvas canvas, float cx, float cy, boolean alert)
|
||||
{
|
||||
if (alert)
|
||||
mSignBackgroundPaint.setColor(mAlertColor);
|
||||
else
|
||||
mSignBackgroundPaint.setColor(mBackgroundColor);
|
||||
@Override
|
||||
protected void onDraw(@NonNull Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
canvas.save();
|
||||
canvas.translate(mLeftSystemWindowInset, -mBottomSystemWindowInset);
|
||||
final boolean isLandscape = mWidth > mHeight;
|
||||
|
||||
canvas.drawCircle(cx, cy, mBackgroundRadius, mSignBackgroundPaint);
|
||||
if (!alert)
|
||||
{
|
||||
mSignBorderPaint.setStrokeWidth(mBorderWidth);
|
||||
canvas.drawCircle(cx, cy, mBorderRadius, mSignBorderPaint);
|
||||
if (isLandscape) {
|
||||
final float cy = mHeight / 2;
|
||||
float gap = mWidth * 0.02f;
|
||||
final float totalWidth = 4 * mBackgroundRadius + gap;
|
||||
final float startX = (mWidth - totalWidth) / 2;
|
||||
final float currentSpeedCx = startX + mBackgroundRadius;
|
||||
final float speedLimitCx = currentSpeedCx + 2 * mBackgroundRadius + gap;
|
||||
draw_widgets(canvas, speedLimitCx, currentSpeedCx, cy, true);
|
||||
} else {
|
||||
final float cx = mWidth / 2;
|
||||
float gap = mHeight * 0.02f;
|
||||
final float totalHeight = 4 * mBackgroundRadius + gap;
|
||||
final float startY = (mHeight - totalHeight) / 2;
|
||||
final float speedLimitCy = startY + mBackgroundRadius;
|
||||
final float currentSpeedCy = speedLimitCy + 2 * mBackgroundRadius + gap;
|
||||
draw_widgets(canvas, cx, speedLimitCy, currentSpeedCy, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawText(@NonNull Canvas canvas, float cx, float cy, boolean alert)
|
||||
private void drawCombinedBackground(Canvas canvas, float cx, float cx_or_cy, float cy) {
|
||||
final boolean isLandscape = mWidth > mHeight;
|
||||
float left;
|
||||
float right;
|
||||
float top;
|
||||
float bottom;
|
||||
|
||||
if (isLandscape) {
|
||||
top = cy - mBackgroundRadius;
|
||||
bottom = cy + mBackgroundRadius;
|
||||
left = cx_or_cy - mBackgroundRadius;
|
||||
right = cx + mBackgroundRadius;
|
||||
} else {
|
||||
left = cx - mBackgroundRadius;
|
||||
right = cx + mBackgroundRadius;
|
||||
top = cx_or_cy - mBackgroundRadius;
|
||||
bottom = cy + mBackgroundRadius;
|
||||
}
|
||||
RectF rect = new RectF(left, top, right, bottom);
|
||||
float cornerRadius = mBackgroundRadius;
|
||||
canvas.drawRoundRect(rect, cornerRadius, cornerRadius, mWidgetBackgroundPaint);
|
||||
}
|
||||
|
||||
private void drawUnlimitedSign(@NonNull Canvas canvas, float cx, float cy) {
|
||||
// Paint for stripes
|
||||
Paint stripesPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
stripesPaint.setColor(Color.BLACK);
|
||||
stripesPaint.setStyle(Paint.Style.STROKE);
|
||||
|
||||
// Thickness of the stripes can be relative to the border width or radius
|
||||
float stripeThickness = mBorderWidth * 0.4f;
|
||||
stripesPaint.setStrokeWidth(stripeThickness);
|
||||
|
||||
float r = mBackgroundRadius;
|
||||
|
||||
// Direction vector for the diagonal lines (top-right to bottom-left)
|
||||
float dx = -1.0f / (float)Math.sqrt(2);
|
||||
float dy = 1.0f / (float)Math.sqrt(2);
|
||||
|
||||
// Perpendicular vector to D (rotate by +90°)
|
||||
float px = -dy;
|
||||
float py = dx;
|
||||
|
||||
// Increase lineSpacing to spread stripes further apart
|
||||
float lineSpacing = r * 0.12f; // slightly larger than 0.1f
|
||||
|
||||
// Use a scale factor to shorten the lines
|
||||
float lineScale = 0.8f; // reduce from full radius to 85% radius
|
||||
|
||||
int[] offsets = {-2, -1, 0, 1, 2};
|
||||
|
||||
// Draw 5 parallel stripes
|
||||
for (int i : offsets) {
|
||||
float ox = i * lineSpacing * px;
|
||||
float oy = i * lineSpacing * py;
|
||||
|
||||
// Start and end points of the line, shortened by lineScale
|
||||
float sx = cx + dx * r * lineScale + ox;
|
||||
float sy = cy + dy * r * lineScale + oy;
|
||||
float ex = cx - dx * r * lineScale + ox;
|
||||
float ey = cy - dy * r * lineScale + oy;
|
||||
|
||||
canvas.drawLine(sx, sy, ex, ey, stripesPaint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void drawSpeedLimitSign(@NonNull Canvas canvas, float cx, float cy) {
|
||||
// Draw the sign background and border as before
|
||||
mSignBackgroundPaint.setColor(mBackgroundColor);
|
||||
canvas.drawCircle(cx, cy, mBackgroundRadius, mSignBackgroundPaint);
|
||||
|
||||
if (mSpeedLimitMps == 0) {
|
||||
// Unlimited speed scenario: Draw the special no-limit pattern
|
||||
mSignUnlimitedBorderPaint.setStrokeWidth(mBorderWidth);
|
||||
canvas.drawCircle(cx, cy, mBorderRadius * DefaultValues.BORDER_RADIUS_RATIO, mSignUnlimitedBorderPaint);
|
||||
drawUnlimitedSign(canvas, cx, cy);
|
||||
}
|
||||
else if (mSpeedLimitStr != null && mSpeedLimitMps > 0) {
|
||||
// Normal speed limit scenario: Draw the text
|
||||
mSignBorderPaint.setStrokeWidth(mBorderWidth);
|
||||
canvas.drawCircle(cx, cy, mBorderRadius * DefaultValues.BORDER_RADIUS_RATIO, mSignBorderPaint);
|
||||
drawSpeedLimitText(canvas, cx, cy);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawSpeedLimitText(@NonNull Canvas canvas, float cx, float cy)
|
||||
{
|
||||
if (mSpeedLimitStr == null)
|
||||
return;
|
||||
|
||||
if (alert)
|
||||
mTextPaint.setColor(mTextAlertColor);
|
||||
else
|
||||
mTextPaint.setColor(mTextColor);
|
||||
mTextPaint.setColor(mTextColor);
|
||||
|
||||
final Rect textBounds = new Rect();
|
||||
mTextPaint.getTextBounds(mSpeedLimitStr, 0, mSpeedLimitStr.length(), textBounds);
|
||||
|
@ -172,32 +390,106 @@ public class SpeedLimitView extends View
|
|||
canvas.drawText(mSpeedLimitStr, cx, textY, mTextPaint);
|
||||
}
|
||||
|
||||
AndrewShkrob
commented
Review
```suggestion
private void drawWidgets(@NonNull Canvas canvas, float cx, float cx_or_cy, float cy, boolean isLandscape) {
```
|
||||
private void drawCurrentSpeedSign(@NonNull Canvas canvas, float cx, float cy, boolean alert) {
|
||||
// Change background color based on alert state
|
||||
mCurrentSpeedBackgroundPaint.setColor(mBackgroundColor);
|
||||
// Draw current speed circle (background)
|
||||
canvas.drawCircle(cx, cy, mBackgroundRadius, mCurrentSpeedBackgroundPaint);
|
||||
// Draw border around current speed circle
|
||||
if (alert) {
|
||||
mCurrentSpeedBackgroundPaint.setColor(mAlertColor);
|
||||
canvas.drawCircle(cx, cy, mBackgroundRadius * DefaultValues.BORDER_RADIUS_RATIO * 0.95f, mCurrentSpeedBackgroundPaint);
|
||||
}
|
||||
mCurrentSpeedBorderPaint.setStrokeWidth(mBorderWidth / 2);
|
||||
canvas.drawCircle(cx, cy, mBorderRadius, mCurrentSpeedBorderPaint);
|
||||
drawCurrentSpeedText(canvas, cx, cy, alert);
|
||||
}
|
||||
|
||||
private void drawCurrentSpeedText(@NonNull Canvas canvas, float cx, float cy, boolean alert) {
|
||||
if (mCurrentSpeedStr == null || mCurrentSpeedUnitsStr == null)
|
||||
return;
|
||||
// Change text color based on alert state
|
||||
if (alert) {
|
||||
mCurrentSpeedTextPaint.setColor(mTextAlertColor);
|
||||
mCurrentSpeedUnitsTextPaint.setColor(mTextAlertColor);
|
||||
} else {
|
||||
mCurrentSpeedTextPaint.setColor(mTextColor);
|
||||
mCurrentSpeedUnitsTextPaint.setColor(mTextColor);
|
||||
}
|
||||
final Rect speedTextBounds = new Rect();
|
||||
mCurrentSpeedTextPaint.getTextBounds(mCurrentSpeedStr, 0, mCurrentSpeedStr.length(), speedTextBounds);
|
||||
final Rect unitsTextBounds = new Rect();
|
||||
mCurrentSpeedUnitsTextPaint.getTextBounds(mCurrentSpeedUnitsStr, 0, mCurrentSpeedUnitsStr.length(), unitsTextBounds);
|
||||
// Position speed text
|
||||
float speedTextY = cy - (float) speedTextBounds.height() / 2 + speedTextBounds.height();
|
||||
// Position units text
|
||||
float unitsTextY = speedTextY + unitsTextBounds.height() + 10f;
|
||||
// Draw speed text
|
||||
canvas.drawText(mCurrentSpeedStr, cx, speedTextY, mCurrentSpeedTextPaint);
|
||||
// Draw units text
|
||||
canvas.drawText(mCurrentSpeedUnitsStr, cx, unitsTextY, mCurrentSpeedUnitsTextPaint);
|
||||
}
|
||||
|
||||
@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());
|
||||
final float paddingX = getPaddingLeft() + getPaddingRight();
|
||||
final float paddingY = getPaddingTop() + getPaddingBottom();
|
||||
mWidth = w - paddingX;
|
||||
mHeight = h - paddingY;
|
||||
|
||||
mWidth = (float) w - paddingX;
|
||||
mHeight = (float) h - paddingY;
|
||||
mBackgroundRadius = Math.min(mWidth, mHeight) / 2;
|
||||
mBorderWidth = mBackgroundRadius * 2 * DefaultValues.BORDER_WIDTH_RATIO;
|
||||
boolean isLandscape = mWidth > mHeight;
|
||||
float gap = (isLandscape) ? mWidth * 0.1f : mHeight * 0.1f;
|
||||
// Compute maximum possible radius
|
||||
mBackgroundRadius = (isLandscape) ? (mWidth - gap) / 4 : (mHeight - gap) / 4;
|
||||
// Ensure the radius does not exceed half of the width
|
||||
mBackgroundRadius = (isLandscape) ? Math.min(mBackgroundRadius, mHeight / 2) : Math.min(mBackgroundRadius, mWidth / 2);
|
||||
mBorderWidth = mBackgroundRadius * 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()
|
||||
{
|
||||
if (mSpeedLimitStr == null)
|
||||
return;
|
||||
private void configureTextSize() {
|
||||
// Use reference strings to keep text size consistent
|
||||
configureTextSizeForString(mTextPaint); // For speed limit
|
||||
configureCurrentSpeedTextSize(); // For current speed and units
|
||||
}
|
||||
private void configureCurrentSpeedTextSize() {
|
||||
final float textRadius = mBorderRadius * 0.75f - mCurrentSpeedBorderPaint.getStrokeWidth();
|
||||
final float availableHeight = 2 * textRadius;
|
||||
float speedTextHeightRatio = 0.75f;
|
||||
float unitsTextHeightRatio = 0.2f;
|
||||
float speedTextHeight = availableHeight * speedTextHeightRatio;
|
||||
float unitsTextHeight = availableHeight * unitsTextHeightRatio;
|
||||
float speedTextSize = findMaxTextSizeForHeight("299", mCurrentSpeedTextPaint, speedTextHeight);
|
||||
float unitsTextSize = findMaxTextSizeForHeight("km/h", mCurrentSpeedUnitsTextPaint, unitsTextHeight);
|
||||
mCurrentSpeedTextPaint.setTextSize(speedTextSize);
|
||||
mCurrentSpeedUnitsTextPaint.setTextSize(unitsTextSize);
|
||||
}
|
||||
private float findMaxTextSizeForHeight(String text, Paint paint, float targetHeight) {
|
||||
float lowerBound = 0;
|
||||
float upperBound = targetHeight;
|
||||
float textSize = targetHeight;
|
||||
final Rect textBounds = new Rect();
|
||||
while (upperBound - lowerBound > 1f) {
|
||||
textSize = (lowerBound + upperBound) / 2;
|
||||
paint.setTextSize(textSize);
|
||||
paint.getTextBounds(text, 0, text.length(), textBounds);
|
||||
if (textBounds.height() <= targetHeight)
|
||||
lowerBound = textSize;
|
||||
else
|
||||
upperBound = textSize;
|
||||
}
|
||||
return lowerBound;
|
||||
}
|
||||
|
||||
final String text = mSpeedLimitStr;
|
||||
private void configureTextSizeForString(Paint textPaint) {
|
||||
final float textRadius = mBorderRadius - mBorderWidth;
|
||||
final float textMaxSize = 2 * textRadius;
|
||||
final float textMaxSizeSquared = (float) Math.pow(textMaxSize, 2);
|
||||
final float textMaxSizeSquared = textMaxSize * textMaxSize;
|
||||
|
||||
float lowerBound = 0;
|
||||
float upperBound = textMaxSize;
|
||||
|
@ -207,15 +499,15 @@ public class SpeedLimitView extends View
|
|||
while (lowerBound <= upperBound)
|
||||
{
|
||||
textSize = (lowerBound + upperBound) / 2;
|
||||
mTextPaint.setTextSize(textSize);
|
||||
mTextPaint.getTextBounds(text, 0, text.length(), textBounds);
|
||||
textPaint.setTextSize(textSize);
|
||||
textPaint.getTextBounds("180", 0, 3, textBounds);
|
||||
|
||||
if (Math.pow(textBounds.width(), 2) + Math.pow(textBounds.height(), 2) <= textMaxSizeSquared)
|
||||
if (textBounds.width() * textBounds.width() + textBounds.height() * textBounds.height() <= textMaxSizeSquared)
|
||||
lowerBound = textSize + 1;
|
||||
else
|
||||
upperBound = textSize - 1;
|
||||
}
|
||||
|
||||
mTextPaint.setTextSize(Math.max(1, textSize));
|
||||
textPaint.setTextSize(Math.max(1, textSize));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,9 +33,6 @@ public class NavMenu
|
|||
private final View mHeaderFrame;
|
||||
|
||||
private final ImageView mTts;
|
||||
private final View mSpeedViewContainer;
|
||||
private final TextView mSpeedValue;
|
||||
private final TextView mSpeedUnits;
|
||||
private final TextView mTimeHourValue;
|
||||
private final TextView mTimeHourUnits;
|
||||
private final TextView mTimeMinuteValue;
|
||||
|
@ -94,10 +91,6 @@ public class NavMenu
|
|||
}
|
||||
});
|
||||
|
||||
// Bottom frame
|
||||
mSpeedViewContainer = bottomFrame.findViewById(R.id.speed_view_container);
|
||||
mSpeedValue = bottomFrame.findViewById(R.id.speed_value);
|
||||
mSpeedUnits = bottomFrame.findViewById(R.id.speed_dimen);
|
||||
mTimeHourValue = bottomFrame.findViewById(R.id.time_hour_value);
|
||||
mTimeHourUnits = bottomFrame.findViewById(R.id.time_hour_dimen);
|
||||
mTimeMinuteValue = bottomFrame.findViewById(R.id.time_minute_value);
|
||||
|
@ -213,20 +206,6 @@ public class NavMenu
|
|||
return;
|
||||
|
||||
Pair<String, String> speedAndUnits = StringUtils.nativeFormatSpeedAndUnits(last.getSpeed());
|
||||
mSpeedValue.setText(speedAndUnits.first);
|
||||
|
||||
if (info.speedLimitMps > 0.0 && last.getSpeed() > info.speedLimitMps)
|
||||
{
|
||||
if (info.isSpeedCamLimitExceeded())
|
||||
mSpeedValue.setTextColor(ContextCompat.getColor(mActivity, R.color.white_primary));
|
||||
else
|
||||
mSpeedValue.setTextColor(ContextCompat.getColor(mActivity, R.color.base_red));
|
||||
}
|
||||
else
|
||||
mSpeedValue.setTextColor(ThemeUtils.getColor(mActivity, android.R.attr.textColorPrimary));
|
||||
|
||||
mSpeedUnits.setText(speedAndUnits.second);
|
||||
mSpeedViewContainer.setActivated(info.isSpeedCamLimitExceeded());
|
||||
}
|
||||
|
||||
public void update(@NonNull RoutingInfo info)
|
||||
|
|
|
@ -25,29 +25,6 @@
|
|||
android:padding="@dimen/nav_frame_padding"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
<include
|
||||
layout="@layout/map_buttons_bookmarks"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/btn_search"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/btn_search" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="@dimen/margin_half"
|
||||
app:layout_constraintBottom_toTopOf="@+id/btn_bookmarks"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/map_buttons_inner_right"
|
||||
|
@ -60,11 +37,37 @@
|
|||
android:padding="@dimen/nav_frame_padding"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
<include
|
||||
layout="@layout/map_buttons_bookmarks"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="@dimen/zoom_buttons_margin"
|
||||
app:layout_constraintBottom_toTopOf="@+id/zoom_buttons_container"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/btn_search"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/btn_search" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="@dimen/margin_half"
|
||||
app:layout_constraintBottom_toTopOf="@+id/btn_bookmarks"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<include
|
||||
layout="@layout/map_buttons_zoom"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginTop="@dimen/zoom_buttons_margin"
|
||||
android:layout_marginBottom="@dimen/zoom_buttons_margin"
|
||||
app:layout_constraintBottom_toTopOf="@+id/my_position"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
|
|
@ -18,21 +18,6 @@
|
|||
android:clipToPadding="false"
|
||||
android:padding="@dimen/nav_frame_padding"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
<include
|
||||
layout="@layout/map_buttons_bookmarks"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="@dimen/margin_half"
|
||||
app:layout_constraintBottom_toTopOf="@+id/btn_bookmarks"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/map_buttons_inner_right"
|
||||
|
@ -44,6 +29,24 @@
|
|||
android:clipToPadding="false"
|
||||
android:padding="@dimen/nav_frame_padding"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<include
|
||||
layout="@layout/map_buttons_bookmarks"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="@dimen/zoom_buttons_margin"
|
||||
app:layout_constraintBottom_toTopOf="@+id/zoom_buttons_container"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="@dimen/margin_half"
|
||||
app:layout_constraintBottom_toTopOf="@+id/btn_bookmarks"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<include
|
||||
layout="@layout/map_buttons_zoom"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
android:id="@+id/search_frame"
|
||||
android:layout_width="160dp"
|
||||
android:layout_height="160dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginStart="-56dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="-56dp"
|
||||
android:background="?searchLayoutBackground"
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible">
|
||||
|
@ -23,7 +23,7 @@
|
|||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginStart="@dimen/margin_half_plus"
|
||||
android:layout_marginEnd="@dimen/margin_half_plus"
|
||||
android:layout_marginTop="@dimen/margin_half"
|
||||
android:contentDescription="@string/category_fuel"
|
||||
app:srcCompat="@drawable/ic_routing_fuel_on" />
|
||||
|
@ -31,13 +31,13 @@
|
|||
android:id="@+id/search_parking"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_marginTop="@dimen/margin_base_plus"
|
||||
android:layout_toEndOf="@id/search_fuel"
|
||||
android:layout_toStartOf="@id/search_fuel"
|
||||
android:contentDescription="@string/category_parking"
|
||||
app:srcCompat="@drawable/ic_routing_parking_on" />
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/search_eat"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:contentDescription="@string/category_eat"
|
||||
|
@ -47,7 +47,7 @@
|
|||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="@dimen/margin_base_plus"
|
||||
android:layout_toEndOf="@id/search_fuel"
|
||||
android:layout_toStartOf="@id/search_fuel"
|
||||
android:contentDescription="@string/category_shopping"
|
||||
app:srcCompat="@drawable/ic_routing_food_on" />
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
|
@ -55,7 +55,7 @@
|
|||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginStart="@dimen/margin_half_plus"
|
||||
android:layout_marginEnd="@dimen/margin_half_plus"
|
||||
android:layout_marginBottom="@dimen/margin_half"
|
||||
android:contentDescription="@string/category_atm"
|
||||
app:srcCompat="@drawable/ic_routing_atm_on" />
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:background="#20FF0000"
|
||||
tools:showIn="@layout/layout_nav">
|
||||
tools:showIn="@layout/layout_nav"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false">
|
||||
<FrameLayout
|
||||
android:id="@+id/street_frame"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -113,7 +115,7 @@
|
|||
android:layout_margin="@dimen/margin_half"
|
||||
android:padding="@dimen/margin_half"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toEndOf="@+id/nav_speed_limit"
|
||||
app:layout_constraintStart_toEndOf="@+id/nav_next_turn_container"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/street_frame"
|
||||
app:activeLaneTintColor="?navLaneArrowActiveColor"
|
||||
|
@ -124,12 +126,12 @@
|
|||
tools:visibility="visible" />
|
||||
|
||||
<app.organicmaps.widget.SpeedLimitView
|
||||
android:id="@+id/nav_speed_limit"
|
||||
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" />
|
||||
android:id="@+id/nav_speed_limit"
|
||||
android:layout_width="110dp"
|
||||
android:layout_height="60dp"
|
||||
app:editModeCurrentSpeed="90"
|
||||
app:editModeSpeedLimit="120"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="88dp" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -13,42 +13,6 @@
|
|||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.5"/>
|
||||
|
||||
<!-- Speed -->
|
||||
<LinearLayout
|
||||
android:id="@+id/speed_view_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@drawable/speed_cams_bg"
|
||||
android:gravity="center"
|
||||
android:minWidth="@dimen/nav_numbers_side_min_width">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/speed_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:includeFontPadding="false"
|
||||
android:lines="1"
|
||||
android:textAppearance="@style/MwmTextAppearance.NavMenu.Number"
|
||||
tools:text="999" />
|
||||
|
||||
<!-- Speed -->
|
||||
<TextView
|
||||
android:id="@+id/speed_dimen"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:includeFontPadding="false"
|
||||
android:lines="1"
|
||||
android:textAppearance="@style/MwmTextAppearance.NavMenu.Number.Dimension"
|
||||
tools:background="#20FF0000"
|
||||
tools:text="km/h" />
|
||||
</LinearLayout>
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1.25"/>
|
||||
|
||||
<!-- Time -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:background="#20FF0000"
|
||||
tools:showIn="@layout/layout_nav">
|
||||
tools:showIn="@layout/layout_nav"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false">
|
||||
<FrameLayout
|
||||
android:id="@+id/street_frame"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -113,7 +115,7 @@
|
|||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:layout_marginTop="@dimen/margin_half"
|
||||
android:padding="@dimen/margin_half"
|
||||
android:visibility="gone"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/nav_next_turn_container"
|
||||
app:layout_constraintTop_toBottomOf="@id/street_frame"
|
||||
|
@ -127,11 +129,10 @@
|
|||
<app.organicmaps.widget.SpeedLimitView
|
||||
android:id="@+id/nav_speed_limit"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_margin="@dimen/margin_half"
|
||||
android:layout_height="110dp"
|
||||
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" />
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="140dp" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -25,29 +25,6 @@
|
|||
android:padding="@dimen/nav_frame_padding"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
<include
|
||||
layout="@layout/map_buttons_bookmarks"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginStart="@dimen/margin_half"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/btn_search" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/btn_search"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/btn_search" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/map_buttons_inner_right"
|
||||
|
@ -60,6 +37,30 @@
|
|||
android:padding="@dimen/nav_frame_padding"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
<include
|
||||
layout="@layout/map_buttons_bookmarks"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/btn_search" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/btn_search"
|
||||
app:layout_constraintEnd_toEndOf="@+id/btn_search"
|
||||
app:layout_constraintTop_toTopOf="@+id/btn_search" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/my_position" />
|
||||
<include
|
||||
layout="@layout/map_buttons_zoom"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -19,21 +19,7 @@
|
|||
android:padding="@dimen/nav_frame_padding"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
<include
|
||||
layout="@layout/map_buttons_bookmarks"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="@dimen/margin_half"
|
||||
app:layout_constraintBottom_toTopOf="@+id/btn_bookmarks"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/map_buttons_inner_right"
|
||||
|
@ -46,14 +32,30 @@
|
|||
android:padding="@dimen/nav_frame_padding"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
<include
|
||||
layout="@layout/map_buttons_bookmarks"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/btn_search" />
|
||||
<include
|
||||
layout="@layout/map_buttons_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/my_position" />
|
||||
|
||||
<include
|
||||
layout="@layout/map_buttons_zoom"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginStart="@dimen/margin_half"
|
||||
app:layout_constraintStart_toEndOf="@+id/my_position"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="@dimen/margin_half"
|
||||
app:layout_constraintBottom_toTopOf="@+id/my_position"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
<include
|
||||
layout="@layout/map_buttons_myposition"
|
||||
|
@ -61,6 +63,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -13,46 +13,46 @@
|
|||
android:id="@+id/search_frame"
|
||||
android:layout_width="286dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:background="?searchLayoutBackground"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/margin_quarter"
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible">
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/search_fuel"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="50dp"
|
||||
android:contentDescription="@string/category_fuel"
|
||||
app:srcCompat="@drawable/ic_routing_fuel_on" />
|
||||
android:id="@+id/search_parking"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:contentDescription="@string/category_parking"
|
||||
app:srcCompat="@drawable/ic_routing_parking_on" />
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/search_parking"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/margin_half"
|
||||
android:contentDescription="@string/category_parking"
|
||||
app:srcCompat="@drawable/ic_routing_parking_on" />
|
||||
android:id="@+id/search_eat"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:contentDescription="@string/category_eat"
|
||||
app:srcCompat="@drawable/ic_routing_eat_on" />
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/search_eat"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/margin_half"
|
||||
android:contentDescription="@string/category_eat"
|
||||
app:srcCompat="@drawable/ic_routing_eat_on" />
|
||||
android:id="@+id/search_food"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:contentDescription="@string/category_shopping"
|
||||
app:srcCompat="@drawable/ic_routing_food_on" />
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/search_food"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/margin_half"
|
||||
android:contentDescription="@string/category_shopping"
|
||||
app:srcCompat="@drawable/ic_routing_food_on" />
|
||||
android:id="@+id/search_atm"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:contentDescription="@string/category_atm"
|
||||
app:srcCompat="@drawable/ic_routing_atm_on" />
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/search_atm"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/margin_half"
|
||||
android:contentDescription="@string/category_atm"
|
||||
app:srcCompat="@drawable/ic_routing_atm_on" />
|
||||
android:id="@+id/search_fuel"
|
||||
style="@style/MwmWidget.MapButton.Search"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:contentDescription="@string/category_fuel"
|
||||
app:srcCompat="@drawable/ic_routing_fuel_on" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
<resources>
|
||||
<declare-styleable name="SpeedLimitView">
|
||||
<attr name="BackgroundColor" format="color" />
|
||||
<attr name="WidgetBackgroundColor" format="color" />
|
||||
AndrewShkrob
commented
What's the difference between What's the difference between `BackgroundColor` and `WidgetBackgroundColor`?
It should be possible to understand it from the name.
Btw, why do these values have names starting from upper case and values below have names starting from lower case?
They all should start from lower case letters like any other android's XML value.
|
||||
<attr name="borderColor" format="color" />
|
||||
<attr name="unlimitedBorderColor" format="color" />
|
||||
<attr name="alertColor" format="color" />
|
||||
<attr name="textColor" format="color" />
|
||||
<attr name="textAlertColor" format="color" />
|
||||
|
|
Reference in a new issue