Пример #1
0
        protected override void OnDraw(ACanvas canvas)
        {
            if (Element == null)
            {
                return;
            }

            var control = (CanvasView)Element;

            SetClipChildren(true);

            //Create path to clip the child
            if (control.Sides != 4)
            {
                using (var path = PolygonUtils.GetPolygonCornerPath(Width, Height, control.Sides, control.CornerRadius.TopLeft, control.OffsetAngle))
                {
                    canvas.Save();
                    canvas.ClipPath(path);
                }
            }
            else
            {
                using (var path = new Path())
                {
                    path.AddRoundRect(new RectF(0, 0, Width, Height), GetRadii(control), Path.Direction.Ccw);

                    canvas.Save();
                    canvas.ClipPath(path);
                }
            }

            DrawBorder(canvas, control);
        }
Пример #2
0
        public override void GetOutline(global::Android.Views.View view, Outline outline)
        {
            if (_pancake.Sides != 4)
            {
                var cornerRadius = (view.Width / _pancake.Width) * _pancake.CornerRadius.TopLeft;
                var hexPath      = PolygonUtils.GetPolygonCornerPath(view.Width, view.Height, _pancake.Sides, cornerRadius, _pancake.OffsetAngle);
                if (hexPath.IsConvex)
                {
                    outline.SetConvexPath(hexPath);
                }

                return;
            }

            // TODO: Figure out how to clip individual rounded corners with different radii.
            outline.SetRoundRect(new Rect(0, 0, view.Width, view.Height), _convertToPixels(_pancake.CornerRadius.TopLeft));
        }
Пример #3
0
        protected override bool DrawChild(ACanvas canvas, global::Android.Views.View child, long drawingTime)
        {
            if (Element == null)
            {
                return(false);
            }

            var control = (CanvasView)Element;

            SetClipChildren(true);

            //Create path to clip the child
            if (control.Sides != 4)
            {
                using (var path = PolygonUtils.GetPolygonCornerPath(Width, Height, control.Sides, control.CornerRadius.TopLeft, control.OffsetAngle))
                {
                    canvas.Save();
                    canvas.ClipPath(path);
                }
            }
            else
            {
                using (var path = new Path())
                {
                    path.AddRoundRect(new RectF(0, 0, Width, Height), GetRadii(control), Path.Direction.Ccw);

                    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, control);

            return(result);
        }
Пример #4
0
        private void DrawBorder(ACanvas canvas, CanvasView control)
        {
            if (control.BorderThickness > 0)
            {
                var  borderThickness      = Context.ToPixels(control.BorderThickness);
                var  halfBorderThickness  = borderThickness / 2;
                bool hasShadowOrElevation = control.HasShadow || 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 = PolygonUtils.GetPolygonCornerPath(Width, Height, control.Sides, control.CornerRadius.TopLeft, control.OffsetAngle);
                                }
                                else
                                {
                                    path = new Path();
                                    path.AddRoundRect(rect, GetRadii(control), direction);
                                }

                                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);
                            }
            }
        }
Пример #5
0
        void DrawBackground(ACanvas canvas, int width, int height, CornerRadius cornerRadius, bool pressed)
        {
            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 = PolygonUtils.GetPolygonCornerPath(width, height, _pancake.Sides, _pancake.CornerRadius.TopLeft, _pancake.OffsetAngle);
                        }
                        else
                        {
                            using (var rect = new RectF(0, 0, width, height))
                            {
                                float topLeft     = _convertToPixels(cornerRadius.TopLeft);
                                float topRight    = _convertToPixels(cornerRadius.TopRight);
                                float bottomRight = _convertToPixels(cornerRadius.BottomRight);
                                float bottomLeft  = _convertToPixels(cornerRadius.BottomLeft);

                                if (!_pancake.HasShadow || _pancake.Elevation > 0)
                                {
                                    path.AddRoundRect(rect, new float[] { topLeft, topLeft, topRight, topRight, bottomRight, bottomRight, bottomLeft, bottomLeft }, direction);
                                }
                                else
                                {
                                    path.AddRoundRect(rect, new float[] { topLeft, topLeft, topLeft, topLeft, topLeft, topLeft, topLeft, topLeft }, direction);
                                }
                            }
                        }

                        if ((_pancake.BackgroundGradientStartColor != default(Xamarin.Forms.Color) && _pancake.BackgroundGradientEndColor != default(Xamarin.Forms.Color)) || (_pancake.BackgroundGradientStops != null && _pancake.BackgroundGradientStops.Any()))
                        {
                            var angle = _pancake.BackgroundGradientAngle / 360.0;

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

                            if (_pancake.BackgroundGradientStops != null && _pancake.BackgroundGradientStops.Count > 0)
                            {
                                // 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(width - (float)a, (float)b, width - (float)c, (float)d, colors, locations, Shader.TileMode.Clamp);
                                paint.SetShader(shader);
                            }
                            else
                            {
                                // Only two colors provided, use that.
                                var shader = new LinearGradient(width - (float)a, (float)b, width - (float)c, (float)d, _pancake.BackgroundGradientStartColor.ToAndroid(), _pancake.BackgroundGradientEndColor.ToAndroid(), 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);
                    }
        }