Skip to content

Commit

Permalink
Test map button shadow via ShapeDrawable
Browse files Browse the repository at this point in the history
  • Loading branch information
Chumva committed Sep 11, 2024
1 parent b72200c commit 5daf8c0
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.osmand.plus.settings.backend.preferences;

import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
Expand Down Expand Up @@ -108,7 +108,7 @@ public CommonPreference<Integer> getFabMarginYLandscape() {
return fabMarginYLandscape;
}

public static void setFabButtonMargin(@Nullable MapActivity mapActivity, @NonNull ImageView fabButton,
public static void setFabButtonMargin(@Nullable MapActivity mapActivity, @NonNull View fabButton,
FrameLayout.LayoutParams params,
@Nullable Pair<Integer, Integer> fabMargin,
int defRightMargin, int defBottomMargin) {
Expand Down
2 changes: 1 addition & 1 deletion OsmAnd/src/net/osmand/plus/utils/AndroidUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1355,7 +1355,7 @@ public static <T extends Serializable> T getSerializable(@NonNull Bundle bundle,
}
}

public static View.OnTouchListener getMoveFabOnTouchListener(@NonNull OsmandApplication app, @Nullable MapActivity mapActivity, @NonNull ImageView fabButton, @NonNull FabMarginPreference preference) {
public static View.OnTouchListener getMoveFabOnTouchListener(@NonNull OsmandApplication app, @Nullable MapActivity mapActivity, @NonNull View fabButton, @NonNull FabMarginPreference preference) {
return new View.OnTouchListener() {
private int initialMarginX = 0;
private int initialMarginY = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;
Expand Down Expand Up @@ -85,7 +83,7 @@ public void update() {
if (this.mapRotation != mapRotation) {
this.mapRotation = mapRotation;

if (getDrawable() instanceof CompassDrawable drawable) {
if (imageView.getDrawable() instanceof CompassDrawable drawable) {
drawable.setMapRotation(mapRotation);
}
invalidate();
Expand Down Expand Up @@ -178,7 +176,7 @@ private void showCompassModeWidgetDialog() {
}

@Nullable
public ImageView moveToSpecialPosition(@NonNull ViewGroup container, @NonNull LayoutParams params) {
public View moveToSpecialPosition(@NonNull ViewGroup container, @NonNull ViewGroup.LayoutParams params) {
ViewGroup parent = (ViewGroup) getParent();
if (parent != null) {
cancelHideAnimation();
Expand Down
132 changes: 88 additions & 44 deletions OsmAnd/src/net/osmand/plus/views/controls/maphudbuttons/MapButton.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
package net.osmand.plus.views.controls.maphudbuttons;

import static android.graphics.drawable.GradientDrawable.RECTANGLE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.widget.ImageView.ScaleType.CENTER;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.BIG_SIZE_DP;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.ROUND_RADIUS_DP;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.TRANSPARENT_ALPHA;
import static net.osmand.plus.settings.backend.preferences.FabMarginPreference.setFabButtonMargin;

import android.content.Context;
import android.graphics.Outline;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.widget.FrameLayout;
import android.widget.ImageView;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageButton;
import androidx.core.util.Pair;
import androidx.core.view.ViewCompat;

import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
Expand All @@ -42,18 +49,25 @@
import net.osmand.plus.views.mapwidgets.configure.buttons.MapButtonState;
import net.osmand.util.Algorithms;

public abstract class MapButton extends AppCompatImageButton implements OnAttachStateChangeListener {
import org.jetbrains.annotations.NotNull;

public abstract class MapButton extends FrameLayout implements OnAttachStateChangeListener {

protected final OsmandApplication app;
protected final OsmandSettings settings;
protected final UiUtilities uiUtilities;

protected final ImageView imageView;
protected final Path clipPath = new Path();
protected LayerDrawable shadowDrawable;

protected MapActivity mapActivity;
protected WidgetsVisibilityHelper visibilityHelper;

protected ButtonAppearanceParams appearanceParams;
protected ButtonAppearanceParams customAppearanceParams;

protected int shadowInset;
protected int strokeWidth;
protected boolean nightMode;
protected boolean invalidated = true;
Expand Down Expand Up @@ -85,10 +99,22 @@ public MapButton(@NonNull Context context, @Nullable AttributeSet attrs, int def
this.app = (OsmandApplication) context.getApplicationContext();
this.settings = app.getSettings();
this.uiUtilities = app.getUIUtilities();
this.shadowInset = app.getResources().getDimensionPixelSize(R.dimen.map_button_inset);
this.strokeWidth = app.getResources().getDimensionPixelSize(R.dimen.map_button_stroke);

ViewCompat.setElevation(this, 5.0f);
imageView = new ImageView(context, attrs, defStyleAttr);
imageView.setClickable(false);
imageView.setFocusable(false);
addView(imageView, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT, Gravity.CENTER));

init();
}

protected void init() {
setClipToPadding(false);
addOnAttachStateChangeListener(this);
setBackgroundColor(Color.TRANSPARENT);
setPadding(shadowInset, shadowInset, shadowInset, shadowInset);
setNightMode(app.getDaynightHelper().isNightModeForMapControls());
}

Expand Down Expand Up @@ -161,6 +187,21 @@ public void setShowBottomButtons(boolean showBottomButtons) {
}
}

protected void setIconColor(@ColorInt int iconColor) {
if (this.iconColor != iconColor) {
this.iconColor = iconColor;
this.invalidated = true;
}
}

protected void setBackgroundColors(@ColorInt int backgroundColor, @ColorInt int backgroundPressedColor) {
if (this.backgroundColor != backgroundColor || this.backgroundPressedColor != backgroundPressedColor) {
this.backgroundColor = backgroundColor;
this.backgroundPressedColor = backgroundPressedColor;
this.invalidated = true;
}
}

public void update() {
updateVisibility();
if (getVisibility() != View.VISIBLE) {
Expand All @@ -172,11 +213,7 @@ public void update() {
if (invalidated || !Algorithms.objectEquals(appearanceParams, params) || customAppearanceParams != null) {
this.appearanceParams = customAppearanceParams != null ? customAppearanceParams : params;
this.invalidated = false;

updateIcon();
updateSize();
updateBackground();
updateShadow();
updateContent();
}
}

Expand All @@ -186,19 +223,11 @@ protected void updateColors(boolean nightMode) {
ColorUtilities.getMapButtonBackgroundPressedColor(getContext(), nightMode));
}

protected void setIconColor(@ColorInt int iconColor) {
if (this.iconColor != iconColor) {
this.iconColor = iconColor;
this.invalidated = true;
}
}

protected void setBackgroundColors(@ColorInt int backgroundColor, @ColorInt int backgroundPressedColor) {
if (this.backgroundColor != backgroundColor || this.backgroundPressedColor != backgroundPressedColor) {
this.backgroundColor = backgroundColor;
this.backgroundPressedColor = backgroundPressedColor;
this.invalidated = true;
}
protected void updateContent() {
updateIcon();
updateSize();
updateBackground();
updateShadow();
}

protected void updateIcon() {
Expand All @@ -215,7 +244,7 @@ protected void updateIcon() {
} else {
drawable = iconColor != 0 ? uiUtilities.getPaintedIcon(iconId, iconColor) : uiUtilities.getIcon(iconId);
}
OsmandMapLayer.setMapButtonIcon(this, drawable, CENTER);
OsmandMapLayer.setMapButtonIcon(imageView, drawable, CENTER);
}
}

Expand Down Expand Up @@ -246,28 +275,43 @@ protected void updateBackground() {
pressed.setCornerRadius(cornerRadius);
pressed.setStroke(strokeWidth, ColorUtilities.getColor(context, nightMode ? R.color.map_widget_dark_stroke : R.color.map_widget_light_pressed));

setBackground(AndroidUtils.createPressedStateListDrawable(normal, pressed));
}

private void updateShadow() {
if (appearanceParams.getOpacity() <= TRANSPARENT_ALPHA) {
setOutlineProvider(null);
} else {
setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
Drawable background = view.getBackground();
if (background != null) {
background.getOutline(outline);
} else {
outline.setRect(0, 0, view.getWidth(), view.getHeight());
}
outline.setAlpha(1);
}
});
imageView.setBackground(AndroidUtils.createPressedStateListDrawable(normal, pressed));
}

protected void updateShadow() {
int radius = AndroidUtils.dpToPx(getContext(), appearanceParams.getCornerRadius());
float[] outerRadius = new float[] {radius, radius, radius, radius, radius, radius, radius, radius};

ShapeDrawable drawable = new ShapeDrawable();
drawable.getPaint().setShadowLayer(shadowInset, 0f, 0f, Color.GRAY);
drawable.setShape(new RoundRectShape(outerRadius, null, null));

shadowDrawable = new LayerDrawable(new ShapeDrawable[] {drawable});
shadowDrawable.setLayerInset(0, shadowInset, shadowInset, shadowInset, shadowInset);
}

@Override
protected void onDraw(@NotNull Canvas canvas) {
super.onDraw(canvas);

if (!nightMode) {
drawShadow(canvas);
}
}

protected void drawShadow(@NotNull Canvas canvas) {
canvas.save();
int radius = AndroidUtils.dpToPx(getContext(), appearanceParams.getCornerRadius());
clipPath.reset();
clipPath.addRoundRect(shadowInset, shadowInset, getWidth() - shadowInset,
getHeight() - shadowInset, radius, radius, Direction.CW);

canvas.clipPath(clipPath, Region.Op.DIFFERENCE);
shadowDrawable.setBounds(0, 0, getRight() - getLeft(), getBottom() - getTop());
shadowDrawable.draw(canvas);
canvas.restore();
}

@Override
public void onViewAttachedToWindow(@NonNull View v) {
updateMargins();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,6 @@ protected void updateBackground() {
pressed.setColor(backgroundPressedColor);
pressed.setCornerRadius(cornerRadius);

setBackground(AndroidUtils.createPressedStateListDrawable(normal, pressed));
imageView.setBackground(AndroidUtils.createPressedStateListDrawable(normal, pressed));
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package net.osmand.plus.views.mapwidgets.configure.buttons;

import static net.osmand.aidlapi.OsmAndCustomizationConstants.COMPASS_HUD_ID;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.BIG_SIZE_DP;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.ROUND_RADIUS_DP;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.SMALL_SIZE_DP;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.TRANSPARENT_ALPHA;
import static net.osmand.plus.settings.enums.CompassVisibility.ALWAYS_HIDDEN;
import static net.osmand.plus.settings.enums.CompassVisibility.ALWAYS_VISIBLE;
Expand Down Expand Up @@ -96,7 +96,7 @@ public ButtonAppearanceParams createDefaultAppearanceParams() {
CompassMode compassMode = settings.getCompassMode();
boolean nightMode = app.getDaynightHelper().isNightModeForMapControls();
String iconName = app.getResources().getResourceEntryName(compassMode.getIconId().getIconId(nightMode));
return new ButtonAppearanceParams(iconName, BIG_SIZE_DP, TRANSPARENT_ALPHA, ROUND_RADIUS_DP);
return new ButtonAppearanceParams(iconName, SMALL_SIZE_DP, TRANSPARENT_ALPHA, ROUND_RADIUS_DP);
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package net.osmand.plus.views.mapwidgets.configure.buttons;

import static net.osmand.aidlapi.OsmAndCustomizationConstants.LAYERS_HUD_ID;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.BIG_SIZE_DP;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.ROUND_RADIUS_DP;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.SMALL_SIZE_DP;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.TRANSPARENT_ALPHA;

import androidx.annotation.NonNull;
Expand Down Expand Up @@ -54,6 +54,6 @@ public CommonPreference<Boolean> getVisibilityPref() {
@Override
public ButtonAppearanceParams createDefaultAppearanceParams() {
ApplicationMode appMode = settings.getApplicationMode();
return new ButtonAppearanceParams(appMode.getIconName(), BIG_SIZE_DP, TRANSPARENT_ALPHA, ROUND_RADIUS_DP);
return new ButtonAppearanceParams(appMode.getIconName(), SMALL_SIZE_DP, TRANSPARENT_ALPHA, ROUND_RADIUS_DP);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package net.osmand.plus.views.mapwidgets.configure.buttons;

import static net.osmand.aidlapi.OsmAndCustomizationConstants.QUICK_SEARCH_HUD_ID;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.BIG_SIZE_DP;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.ROUND_RADIUS_DP;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.SMALL_SIZE_DP;
import static net.osmand.plus.quickaction.ButtonAppearanceParams.TRANSPARENT_ALPHA;

import androidx.annotation.NonNull;
Expand Down Expand Up @@ -52,6 +52,6 @@ public int getDefaultLayoutId() {
@NonNull
@Override
public ButtonAppearanceParams createDefaultAppearanceParams() {
return new ButtonAppearanceParams("ic_action_search_dark", BIG_SIZE_DP, TRANSPARENT_ALPHA, ROUND_RADIUS_DP);
return new ButtonAppearanceParams("ic_action_search_dark", SMALL_SIZE_DP, TRANSPARENT_ALPHA, ROUND_RADIUS_DP);
}
}

0 comments on commit 5daf8c0

Please sign in to comment.