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); }
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); } } }