Example #1
0
        private static IDisposable InnerCreateLayers(BindableView view,
                                                     Windows.Foundation.Rect drawArea,
                                                     Brush background,
                                                     Thickness borderThickness,
                                                     Brush borderBrush,
                                                     CornerRadius cornerRadius,
                                                     Action onImageSet
                                                     )
        {
            var disposables = new CompositeDisposable();

            var physicalBorderThickness = borderThickness.LogicalToPhysicalPixels();

            if (cornerRadius != 0)
            {
                if (view is UIElement uiElement && uiElement.FrameRoundingAdjustment is { } fra)
                {
                    drawArea.Height += fra.Height;
                    drawArea.Width  += fra.Width;
                }

                var adjustedArea = drawArea.DeflateBy(physicalBorderThickness);

                using (var backgroundPath = cornerRadius.GetOutlinePath(adjustedArea.ToRectF()))
                {
                    //We only need to set a background if the drawArea is non-zero
                    if (!drawArea.HasZeroArea())
                    {
                        if (background is ImageBrush imageBrushBackground)
                        {
                            //Copy the path because it will be disposed when we exit the using block
                            var pathCopy      = new Path(backgroundPath);
                            var setBackground = DispatchSetImageBrushAsBackground(view, imageBrushBackground, drawArea, onImageSet, pathCopy);
                            disposables.Add(setBackground);
                        }
                        else if (background is AcrylicBrush acrylicBrush)
                        {
                            var apply = acrylicBrush.Subscribe(view, drawArea, backgroundPath);
                            disposables.Add(apply);
                        }
                        else
                        {
                            var fillPaint = background?.GetFillPaint(drawArea) ?? new Paint()
                            {
                                Color = Android.Graphics.Color.Transparent
                            };
                            ExecuteWithNoRelayout(view, v => v.SetBackgroundDrawable(Brush.GetBackgroundDrawable(background, drawArea, fillPaint, backgroundPath)));
                        }
                        disposables.Add(() => ExecuteWithNoRelayout(view, v => v.SetBackgroundDrawable(null)));
                    }

                    if (borderThickness != Thickness.Empty && borderBrush != null && !(borderBrush is ImageBrush))
                    {
                        using (var strokePaint = new Paint(borderBrush.GetStrokePaint(drawArea)))
                        {
                            //Create the path for the outer and inner rectangles that will become our border shape
                            var borderPath = cornerRadius.GetOutlinePath(drawArea.ToRectF());
                            borderPath.AddRoundRect(adjustedArea.ToRectF(), cornerRadius.GetRadii(), Path.Direction.Ccw);

                            var overlay = GetOverlayDrawable(
                                strokePaint,
                                physicalBorderThickness,
                                new global::System.Drawing.Size((int)drawArea.Width, (int)drawArea.Height),
                                borderPath);

                            if (overlay != null)
                            {
                                overlay.SetBounds(0, 0, view.Width, view.Height);
                                SetOverlay(view, disposables, overlay);
                            }
                        }
                    }
                }
            }
            else             // No corner radius
            {
                //We only need to set a background if the drawArea is non-zero
                if (!drawArea.HasZeroArea())
                {
                    if (background is ImageBrush imageBrushBackground)
                    {
                        var setBackground = DispatchSetImageBrushAsBackground(view, imageBrushBackground, drawArea, onImageSet);
                        disposables.Add(setBackground);
                    }
                    else if (background is AcrylicBrush acrylicBrush)
                    {
                        var apply = acrylicBrush.Subscribe(view, drawArea, maskingPath: null);
                        disposables.Add(apply);
                    }
                    else
                    {
                        var fillPaint = background?.GetFillPaint(drawArea) ?? new Paint()
                        {
                            Color = Android.Graphics.Color.Transparent
                        };
                        ExecuteWithNoRelayout(view, v => v.SetBackgroundDrawable(Brush.GetBackgroundDrawable(background, drawArea, fillPaint)));
                    }
                    disposables.Add(() => ExecuteWithNoRelayout(view, v => v.SetBackgroundDrawable(null)));
                }
            }

            if (borderBrush != null && !(borderBrush is ImageBrush))
            {
                //TODO: Handle case that BorderBrush is an ImageBrush
                using (var strokePaint = borderBrush.GetStrokePaint(drawArea))
                {
                    var overlay = GetOverlayDrawable(strokePaint, physicalBorderThickness, new global::System.Drawing.Size(view.Width, view.Height));

                    if (overlay != null)
                    {
                        overlay.SetBounds(0, 0, view.Width, view.Height);
                        SetOverlay(view, disposables, overlay);
                    }
                }
            }

            return(disposables);
        }