diff --git a/src/Core/AndroidNative/maui/src/main/java/com/microsoft/maui/PlatformInterop.java b/src/Core/AndroidNative/maui/src/main/java/com/microsoft/maui/PlatformInterop.java index 1b64806956f5..0760f90da693 100644 --- a/src/Core/AndroidNative/maui/src/main/java/com/microsoft/maui/PlatformInterop.java +++ b/src/Core/AndroidNative/maui/src/main/java/com/microsoft/maui/PlatformInterop.java @@ -2,10 +2,17 @@ import android.content.Context; import android.content.res.ColorStateList; +import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PathEffect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.graphics.drawable.PaintDrawable; import android.net.Uri; +import android.os.Build; +import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -373,6 +380,81 @@ public static ColorStateList createEditTextColorStateList(ColorStateList colorSt return null; } + /** + * Sets many values at once on a Paint object + * @param paint + * @param strokeWidth + * @param strokeJoin + * @param strokeCap + * @param strokeMiter + * @param pathEffect + */ + public static void setPaintValues(Paint paint, float strokeWidth, Paint.Join strokeJoin, Paint.Cap strokeCap, float strokeMiter, PathEffect pathEffect) + { + paint.setStrokeWidth(strokeWidth); + paint.setStrokeJoin(strokeJoin); + paint.setStrokeCap(strokeCap); + paint.setStrokeMiter(strokeMiter); + if (pathEffect != null) { + paint.setPathEffect(pathEffect); + } + } + + /** + * Calls canvas.saveLayer(), draws paths for clipPath & borderPaint, then canvas.restoreToCount() + * @param drawable + * @param canvas + * @param width + * @param height + * @param clipPath + * @param borderPaint + */ + public static void drawMauiDrawablePath(PaintDrawable drawable, Canvas canvas, int width, int height, @NonNull Path clipPath, Paint borderPaint) + { + int saveCount = canvas.saveLayer(0, 0, width, height, null); + + Paint paint = drawable.getPaint(); + if (paint != null) { + canvas.drawPath(clipPath, paint); + } + if (borderPaint != null) { + canvas.drawPath(clipPath, borderPaint); + } + + canvas.restoreToCount(saveCount); + } + + /** + * Gets the value of android.R.attr.windowBackground from the given Context + * @param context + * @return the color or -1 if not found + */ + public static int getWindowBackgroundColor(Context context) + { + TypedValue value = new TypedValue(); + if (!context.getTheme().resolveAttribute(android.R.attr.windowBackground, value, true) && isColorType(value)) { + return value.data; + } else { + return -1; + } + } + + /** + * Needed because TypedValue.isColorType() is only API Q+ + * https://github.com/aosp-mirror/platform_frameworks_base/blob/1d896eeeb8744a1498128d62c09a3aa0a2a29a16/core/java/android/util/TypedValue.java#L266-L268 + * @param value + * @return true if the TypedValue is a Color + */ + private static boolean isColorType(TypedValue value) + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return value.isColorType(); + } else { + // Implementation from AOSP + return (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT); + } + } + private static class ColorStates { static final int[] EMPTY = new int[] { }; diff --git a/src/Core/src/Graphics/MauiDrawable.Android.cs b/src/Core/src/Graphics/MauiDrawable.Android.cs index 499a450abbc2..62d64a3790b0 100644 --- a/src/Core/src/Graphics/MauiDrawable.Android.cs +++ b/src/Core/src/Graphics/MauiDrawable.Android.cs @@ -388,18 +388,12 @@ protected override void OnDraw(Shape? shape, Canvas? canvas, APaint? paint) if (_borderPaint != null) { - _borderPaint.StrokeWidth = _strokeThickness; - _borderPaint.StrokeJoin = _strokeLineJoin; - _borderPaint.StrokeCap = _strokeLineCap; - _borderPaint.StrokeMiter = _strokeMiterLimit * 2; - - if (_borderPathEffect != null) - _borderPaint.SetPathEffect(_borderPathEffect); + PlatformInterop.SetPaintValues(_borderPaint, _strokeThickness, _strokeLineJoin, _strokeLineCap, _strokeMiterLimit * 2, _borderPathEffect); if (_borderColor != null) -#pragma warning disable CA1416 // https://github.com/xamarin/xamarin-android/issues/6962 + { _borderPaint.Color = _borderColor.Value; -#pragma warning restore CA1416 + } else { if (_stroke != null) @@ -427,18 +421,10 @@ protected override void OnDraw(Shape? shape, Canvas? canvas, APaint? paint) } } - if (canvas == null) + if (canvas == null || _clipPath == null) return; - var saveCount = canvas.SaveLayer(0, 0, _width, _height, null); - - if (_clipPath != null && Paint != null) - canvas.DrawPath(_clipPath, Paint); - - if (_clipPath != null && _borderPaint != null) - canvas.DrawPath(_clipPath, _borderPaint); - - canvas.RestoreToCount(saveCount); + PlatformInterop.DrawMauiDrawablePath(this, canvas, _width, _height, _clipPath, _borderPaint); } else { @@ -512,22 +498,10 @@ void InitializeBorderIfNeeded() void SetDefaultBackgroundColor() { - using (var background = new TypedValue()) + var color = PlatformInterop.GetWindowBackgroundColor(_context); + if (color != -1) { - if (_context == null || _context.Theme == null || _context.Resources == null) - return; - - if (_context.Theme.ResolveAttribute(global::Android.Resource.Attribute.WindowBackground, background, true)) - { - var resource = _context.Resources.GetResourceTypeName(background.ResourceId); - var type = resource?.ToLowerInvariant(); - - if (type == "color") - { - var color = new AColor(ContextCompat.GetColor(_context, background.ResourceId)); - _backgroundColor = color; - } - } + _backgroundColor = new AColor(color); } } diff --git a/src/Core/src/maui.aar b/src/Core/src/maui.aar index d98bc8d5be06..d4b3ebc7ab9b 100644 Binary files a/src/Core/src/maui.aar and b/src/Core/src/maui.aar differ