forked from organicmaps/organicmaps
[android] Add current speed widget
Signed-off-by: TobiPeterG <github.threefold020@passmail.net>
This commit is contained in:
parent
1b2c2404ad
commit
f11766a1ab
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);
|
||||
}
|
||||
|
||||
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" />
|
||||
<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" />
|
||||
|
|
Loading…
Add table
Reference in a new issue