protected override void OnDraw(ACanvas canvas)
        {
            if (Element == null)
            {
                return;
            }

            var pancake = Element as PancakeView;

            SetClipChildren(true);

            //Create path to clip the child
            if (pancake.Sides != 4)
            {
                using (var path = DrawingExtensions.CreatePolygonPath(Width, Height, pancake.Sides, pancake.CornerRadius.TopLeft, pancake.OffsetAngle))
                {
                    canvas.Save();
                    canvas.ClipPath(path);
                }
            }
            else
            {
                using (var path = DrawingExtensions.CreateRoundedRectPath(Width, Height,
                                                                          Context.ToPixels(pancake.CornerRadius.TopLeft),
                                                                          Context.ToPixels(pancake.CornerRadius.TopRight),
                                                                          Context.ToPixels(pancake.CornerRadius.BottomRight),
                                                                          Context.ToPixels(pancake.CornerRadius.BottomLeft)))
                {
                    canvas.Save();
                    canvas.ClipPath(path);
                }
            }

            DrawBorder(canvas, pancake);
        }
Example #2
0
        public override void GetOutline(global::Android.Views.View view, Outline outline)
        {
            if (_pancake.Sides != 4)
            {
                var hexPath = DrawingExtensions.CreatePolygonPath(view.Width, view.Height, _pancake.Sides, _pancake.Shadow != null ? 0 : _pancake.CornerRadius.TopLeft, _pancake.OffsetAngle);

                if (hexPath.IsConvex)
                {
                    outline.SetConvexPath(hexPath);
                }
            }
            else
            {
                var path = DrawingExtensions.CreateRoundedRectPath(view.Width, view.Height,
                                                                   _convertToPixels(_pancake.CornerRadius.TopLeft),
                                                                   _convertToPixels(_pancake.CornerRadius.TopRight),
                                                                   _convertToPixels(_pancake.CornerRadius.BottomRight),
                                                                   _convertToPixels(_pancake.CornerRadius.BottomLeft));

                if (path.IsConvex)
                {
                    outline.SetConvexPath(path);
                }
            }
        }
        void DrawBackground(ACanvas canvas, int width, int height, CornerRadius cornerRadius)
        {
            using (var paint = new Paint {
                AntiAlias = true
            })
                using (Path.Direction direction = Path.Direction.Cw)
                    using (Paint.Style style = Paint.Style.Fill)
                    {
                        var path = new Path();

                        if (_pancake.Sides != 4)
                        {
                            path = DrawingExtensions.CreatePolygonPath(width, height, _pancake.Sides, _pancake.CornerRadius.TopLeft, _pancake.OffsetAngle);
                        }
                        else
                        {
                            float topLeft     = _convertToPixels(cornerRadius.TopLeft);
                            float topRight    = _convertToPixels(cornerRadius.TopRight);
                            float bottomRight = _convertToPixels(cornerRadius.BottomRight);
                            float bottomLeft  = _convertToPixels(cornerRadius.BottomLeft);

                            path = DrawingExtensions.CreateRoundedRectPath(width, height, topLeft, topRight, bottomRight, bottomLeft);
                        }

                        if (_pancake.BackgroundGradientStops != null && _pancake.BackgroundGradientStops.Any())
                        {
                            // A range of colors is given. Let's add them.
                            var orderedStops = _pancake.BackgroundGradientStops.OrderBy(x => x.Offset).ToList();
                            var colors       = orderedStops.Select(x => x.Color.ToAndroid().ToArgb()).ToArray();
                            var locations    = orderedStops.Select(x => x.Offset).ToArray();

                            var shader = new LinearGradient((float)(canvas.Width * _pancake.BackgroundGradientStartPoint.X),
                                                            (float)(canvas.Height * _pancake.BackgroundGradientStartPoint.Y),
                                                            (float)(canvas.Width * _pancake.BackgroundGradientEndPoint.X),
                                                            (float)(canvas.Height * _pancake.BackgroundGradientEndPoint.Y),
                                                            colors, locations, Shader.TileMode.Clamp);

                            paint.SetShader(shader);
                        }
                        else
                        {
                            global::Android.Graphics.Color color = _pancake.BackgroundColor.ToAndroid();
                            paint.SetStyle(style);
                            paint.Color = color;
                        }

                        canvas.DrawPath(path, paint);
                    }
        }
        protected override bool DrawChild(ACanvas canvas, global::Android.Views.View child, long drawingTime)
        {
            if (Element == null)
            {
                return(false);
            }

            var pancake = Element as PancakeView;

            SetClipChildren(true);

            //Create path to clip the child
            if (pancake.Sides != 4)
            {
                using (var path = DrawingExtensions.CreatePolygonPath(Width, Height, pancake.Sides, pancake.CornerRadius.TopLeft, pancake.OffsetAngle))
                {
                    canvas.Save();
                    canvas.ClipPath(path);
                }
            }
            else
            {
                using (var path = DrawingExtensions.CreateRoundedRectPath(Width, Height,
                                                                          Context.ToPixels(pancake.CornerRadius.TopLeft),
                                                                          Context.ToPixels(pancake.CornerRadius.TopRight),
                                                                          Context.ToPixels(pancake.CornerRadius.BottomRight),
                                                                          Context.ToPixels(pancake.CornerRadius.BottomLeft)))
                {
                    canvas.Save();
                    canvas.ClipPath(path);
                }
            }

            // Draw the child first so that the border shows up above it.
            var result = base.DrawChild(canvas, child, drawingTime);

            canvas.Restore();

            DrawBorder(canvas, pancake);

            return(result);
        }
        private void DrawBorder(ACanvas canvas, PancakeView pancake)
        {
            if (pancake.Border != null && pancake.Border.Thickness != default)
            {
                var  borderThickness      = Context.ToPixels(pancake.Border.Thickness);
                var  halfBorderThickness  = borderThickness / 2;
                bool hasShadowOrElevation = pancake.Shadow != null && Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop;

                // TODO: This doesn't look entirely right yet when using it with rounded corners.
                using (var paint = new Paint {
                    AntiAlias = true
                })
                    using (Path.Direction direction = Path.Direction.Cw)
                        using (Paint.Style style = Paint.Style.Stroke)
                            using (var rect = new RectF(pancake.Border.DrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? -halfBorderThickness : halfBorderThickness,
                                                        pancake.Border.DrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? -halfBorderThickness : halfBorderThickness,
                                                        pancake.Border.DrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? canvas.Width + halfBorderThickness : canvas.Width - halfBorderThickness,
                                                        pancake.Border.DrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? canvas.Height + halfBorderThickness : canvas.Height - halfBorderThickness))
                            {
                                Path path = null;
                                if (pancake.Sides != 4)
                                {
                                    path = DrawingExtensions.CreatePolygonPath(Width, Height, pancake.Sides, pancake.CornerRadius.TopLeft, pancake.OffsetAngle);
                                }
                                else

                                {
                                    path = DrawingExtensions.CreateRoundedRectPath(Width, Height,
                                                                                   Context.ToPixels(pancake.CornerRadius.TopLeft),
                                                                                   Context.ToPixels(pancake.CornerRadius.TopRight),
                                                                                   Context.ToPixels(pancake.CornerRadius.BottomRight),
                                                                                   Context.ToPixels(pancake.CornerRadius.BottomLeft));
                                }

                                if (pancake.Border.DashPattern.Pattern != null && pancake.Border.DashPattern.Pattern.Length > 0)
                                {
                                    var items = pancake.Border.DashPattern.Pattern.Select(x => Context.ToPixels(Convert.ToSingle(x))).ToArray();

                                    // dashes merge when thickness is increased
                                    // off-distance should be scaled according to thickness
                                    for (int i = 0; i < items.Count(); i++)
                                    {
                                        if (i % 2 != 0)
                                        {
                                            items[i] = items[i] * ((float)pancake.Border.Thickness * 0.5f);
                                        }
                                    }

                                    paint.SetPathEffect(new DashPathEffect(items, 0));
                                }

                                if (pancake.Border.GradientStops != null && pancake.Border.GradientStops.Any())
                                {
                                    // A range of colors is given. Let's add them.
                                    var orderedStops = pancake.Border.GradientStops.OrderBy(x => x.Offset).ToList();
                                    var colors       = orderedStops.Select(x => x.Color.ToAndroid().ToArgb()).ToArray();
                                    var locations    = orderedStops.Select(x => x.Offset).ToArray();

                                    var shader = new LinearGradient((float)(canvas.Width * pancake.Border.GradientStartPoint.X),
                                                                    (float)(canvas.Height * pancake.Border.GradientStartPoint.Y),
                                                                    (float)(canvas.Width * pancake.Border.GradientEndPoint.X),
                                                                    (float)(canvas.Height * pancake.Border.GradientEndPoint.Y),
                                                                    colors, locations, Shader.TileMode.Clamp);
                                    paint.SetShader(shader);
                                }
                                else
                                {
                                    paint.Color = pancake.Border.Color.ToAndroid();
                                }

                                paint.StrokeCap   = Paint.Cap.Square;
                                paint.StrokeWidth = borderThickness;
                                paint.SetStyle(style);

                                canvas.DrawPath(path, paint);
                            }
            }
        }