public override void GetOutline(global::Android.Views.View view, Outline outline) { if (_pancake.Sides != 4) { var hexPath = CatFeeder.Droid.Renderers.ShapeUtils.CreatePolygonPath(view.Width, view.Height, _pancake.Sides, _pancake.HasShadow ? 0 : _pancake.CornerRadius.TopLeft, _pancake.OffsetAngle); if (hexPath.IsConvex) { outline.SetConvexPath(hexPath); } } else { var path = ShapeUtils.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); } } }
protected override void OnDraw(ACanvas canvas) { if (Element == null) { return; } var control = (PancakeView)Element; SetClipChildren(true); //Create path to clip the child if (control.Sides != 4) { using (var path = ShapeUtils.CreatePolygonPath(Width, Height, control.Sides, control.CornerRadius.TopLeft, control.OffsetAngle)) { canvas.Save(); canvas.ClipPath(path); } } else { using (var 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))) { canvas.Save(); canvas.ClipPath(path); } } DrawBorder(canvas, control); }
protected override bool DrawChild(ACanvas canvas, global::Android.Views.View child, long drawingTime) { if (Element == null) { return(false); } var control = (PancakeView)Element; SetClipChildren(true); //Create path to clip the child if (control.Sides != 4) { using (var path = ShapeUtils.CreatePolygonPath(Width, Height, control.Sides, control.CornerRadius.TopLeft, control.OffsetAngle)) { canvas.Save(); canvas.ClipPath(path); } } else { using (var 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))) { 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); }
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); } } }
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 = ShapeUtils.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 = ShapeUtils.CreateRoundedRectPath(width, height, topLeft, topRight, bottomRight, bottomLeft); } 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); } }