Example #1
0
        private void DrawBorder(ACanvas canvas, PancakeView control)
        {
            if (control.BorderThickness > 0)
            {
                var  borderThickness      = Context.ToPixels(control.BorderThickness);
                var  halfBorderThickness  = borderThickness / 2;
                bool hasShadowOrElevation = control.HasShadow || (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop && control.Elevation > 0);

                // 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(control.BorderDrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? -halfBorderThickness : halfBorderThickness,
                                                        control.BorderDrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? -halfBorderThickness : halfBorderThickness,
                                                        control.BorderDrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? canvas.Width + halfBorderThickness : canvas.Width - halfBorderThickness,
                                                        control.BorderDrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? canvas.Height + halfBorderThickness : canvas.Height - halfBorderThickness))
                            {
                                Path path = null;
                                if (control.Sides != 4)
                                {
                                    path = ShapeUtils.CreatePolygonPath(Width, Height, control.Sides, control.CornerRadius.TopLeft, control.OffsetAngle);
                                }
                                else
                                {
                                    path = ShapeUtils.CreateRoundedRectPath(Width, Height,
                                                                            Context.ToPixels(control.CornerRadius.TopLeft),
                                                                            Context.ToPixels(control.CornerRadius.TopRight),
                                                                            Context.ToPixels(control.CornerRadius.BottomRight),
                                                                            Context.ToPixels(control.CornerRadius.BottomLeft));
                                }

                                if (control.BorderIsDashed)
                                {
                                    // dashes merge when thickness is increased
                                    // off-distance should be scaled according to thickness
                                    paint.SetPathEffect(new DashPathEffect(new float[] { 10, 5 * control.BorderThickness }, 0));
                                }

                                if ((control.BorderGradientStartColor != default(Xamarin.Forms.Color) && control.BorderGradientEndColor != default(Xamarin.Forms.Color)) || (control.BorderGradientStops != null && control.BorderGradientStops.Any()))
                                {
                                    var angle = control.BorderGradientAngle / 360.0;

                                    // Calculate the new positions based on angle between 0-360.
                                    var a = canvas.Width * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.75) / 2)), 2);
                                    var b = canvas.Height * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.0) / 2)), 2);
                                    var c = canvas.Width * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.25) / 2)), 2);
                                    var d = canvas.Height * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.5) / 2)), 2);

                                    if (control.BorderGradientStops != null && control.BorderGradientStops.Count > 0)
                                    {
                                        // A range of colors is given. Let's add them.
                                        var orderedStops = control.BorderGradientStops.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(canvas.Width - (float)a, (float)b, canvas.Width - (float)c, (float)d, colors, locations, Shader.TileMode.Clamp);
                                        paint.SetShader(shader);
                                    }
                                    else
                                    {
                                        // Only two colors provided, use that.
                                        var shader = new LinearGradient(canvas.Width - (float)a, (float)b, canvas.Width - (float)c, (float)d, control.BorderGradientStartColor.ToAndroid(), control.BorderGradientEndColor.ToAndroid(), Shader.TileMode.Clamp);
                                        paint.SetShader(shader);
                                    }
                                }
                                else
                                {
                                    paint.Color = control.BorderColor.ToAndroid();
                                }

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

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