Skip to content

Commit

Permalink
Merge pull request #59 from ChasakisD/feature-shapes
Browse files Browse the repository at this point in the history
Add Circle Shape
  • Loading branch information
ChasakisD authored Jan 24, 2020
2 parents f25ddb8 + ce21a7e commit 556f26e
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public override void GetOutline(View view, Outline outline)
}

var clipPath = pathProvider.CreatePath(view.Width, view.Height);
if (!clipPath.IsConvex) return;
if (clipPath == null || !clipPath.IsConvex) return;

outline.SetConvexPath(clipPath);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public void Invalidate()

public Path CreatePath(int width, int height)
{
if (_disposed) return null;

/* If the path is not dirty return it */
if (!IsPathDirty || !(_shape is TShape tShape)) return Path;

Expand All @@ -50,6 +52,8 @@ public Path CreatePath(int width, int height)

public Path CreateBorderedPath(int width, int height)
{
if (_disposed) return null;

/* If the path provider, does not support border, use the default */
if (!IsBorderSupported) return CreatePath(width, height);

Expand All @@ -72,6 +76,8 @@ public Path CreateBorderedPath(int width, int height)

public virtual void SetShape(IBackgroundShape shape)
{
if (_disposed) return;

_shape = shape;

Invalidate();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using Android.Graphics;
using XamarinBackgroundKit.Shapes;

namespace XamarinBackgroundKit.Android.PathProviders
{
public class CirclePathProvider : BasePathProvider<Circle>
{
public override bool IsBorderSupported => true;

public override void CreatePath(Path path, Circle shape, int width, int height)
{
var radius = Math.Min(width, height) / 2f;

path.AddCircle(width / 2f, height / 2f, radius, Path.Direction.Ccw);
}

public override void CreateBorderedPath(Path path, Circle shape, int width, int height, int strokeWidth)
{
var radius = (Math.Min(width, height) - strokeWidth) / 2f;

path.AddCircle(width / 2f, height / 2f, radius, Path.Direction.Ccw);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public static void Init()
{
Register<Arc>(() => new ArcPathProvider());
Register<Rect>(() => new RectPathProvider());
Register<Circle>(() => new CirclePathProvider());
Register<Diagonal>(() => new DiagonalPathProvider());
Register<Triangle>(() => new TrianglePathProvider());
Register<RoundRect>(() => new RoundRectPathProvider());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class MaterialShapeManager : IDisposable
private Paint _maskPaint;
private AView _nativeView;
private IBackgroundShape _shape;

public IPathProvider PathProvider { get; private set; }

public MaterialShapeManager()
Expand Down Expand Up @@ -118,6 +119,7 @@ private void InitializeClipPath(int width, int height)

/* Always prefer border path. If there is no need, the provider will return the default one */
var clipPath = PathProvider.CreateBorderedPath(width, height);
if (clipPath == null) return;

_clipPath.Reset();
_clipPath.Set(clipPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
<Compile Include="GradientProviders\BaseGradientProvider.cs" />
<Compile Include="GradientProviders\LinearGradientProvider.cs" />
<Compile Include="GradientProviders\GradientProvidersContainer.cs" />
<Compile Include="PathProviders\CirclePathProvider.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.Forms">
Expand Down
59 changes: 59 additions & 0 deletions src/XamarinBackgroundKit.iOS/PathProviders/CirclePathProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using CoreGraphics;
using UIKit;
using XamarinBackgroundKit.Shapes;

namespace XamarinBackgroundKit.iOS.PathProviders
{
public class CirclePathProvider : BasePathProvider<Circle>
{
public override bool IsBorderSupported => true;

public override void CreatePath(Circle shape, CGRect bounds)
{
using (var bezierPath = GetCirclePath(bounds))
{
Path = bezierPath.CGPath;
}
}

public override void CreateBorderedPath(Circle shape, CGRect bounds, double strokeWidth)
{
using (var bezierPath = GetCirclePath(bounds, (float)strokeWidth))
{
BorderPath = bezierPath.CGPath;
}
}

private static UIBezierPath GetCirclePath(CGRect bounds, float borderWidth = 0f)
{
var startX = bounds.Left;
var endX = bounds.Right;
var startY = bounds.Top;
var endY = bounds.Bottom;

var delta = (float)Math.Abs(bounds.Width - bounds.Height) / 2f;

if (bounds.Width > bounds.Height)
{
startX += delta;
endX -= 2 * delta;
}
else if (bounds.Width < bounds.Height)
{
startY += delta;
endY -= 2 * delta;
}

var croppedBounds = new CGRect(
startX, startY, endX, endY);

var strokedCroppedBounds = croppedBounds.Inset(
borderWidth, borderWidth);

var radius = ((float)Math.Min(bounds.Width, bounds.Height) - borderWidth) / 2;

return UIBezierPath.FromRoundedRect(strokedCroppedBounds, radius);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public static void Init()
{
Register<Arc>(() => new ArcPathProvider());
Register<Rect>(() => new RectPathProvider());
Register<Circle>(() => new CirclePathProvider());
Register<Diagonal>(() => new DiagonalPathProvider());
Register<Triangle>(() => new TrianglePathProvider());
Register<RoundRect>(() => new RoundRectPathProvider());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
<Compile Include="GradientProviders\BaseGradientProvider.cs" />
<Compile Include="GradientProviders\LinearGradientProvider.cs" />
<Compile Include="GradientProviders\GradientProvidersContainer.cs" />
<Compile Include="PathProviders\CirclePathProvider.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Naxam.KVOController.iOS">
Expand Down
4 changes: 4 additions & 0 deletions src/XamarinBackgroundKit/Shapes/Circle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace XamarinBackgroundKit.Shapes
{
public class Circle : BaseShape { }
}
65 changes: 51 additions & 14 deletions src/XamarinBackgroundKitSample/ShapeExplorerPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<x:Array Type="{x:Type x:String}">
<x:String>Arc</x:String>
<x:String>Rect</x:String>
<x:String>Circle</x:String>
<x:String>RoundRect</x:String>
<x:String>Diagonal</x:String>
<x:String>Triangle</x:String>
Expand Down Expand Up @@ -120,21 +121,57 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<Label FontSize="24" Text="X" Grid.Row="0" Grid.Column="0" />
<Label FontSize="24" Text="Y" Grid.Row="0" Grid.Column="1" />

<Label FontSize="24" Text="Point A" Grid.Row="1" Grid.ColumnSpan="2" />
<Slider x:Name="PointAX" Grid.Row="2" Grid.Column="0" Maximum="1" Minimum="0" ValueChanged="OnTrianglePointsChanged" />
<Slider x:Name="PointAY" Grid.Row="2" Grid.Column="1" Maximum="1" Minimum="0" ValueChanged="OnTrianglePointsChanged" />

<Label FontSize="24" Text="Point B" Grid.Row="3" Grid.ColumnSpan="2" />
<Slider x:Name="PointBX" Grid.Row="4" Grid.Column="0" Maximum="1" Minimum="0" ValueChanged="OnTrianglePointsChanged" />
<Slider x:Name="PointBY" Grid.Row="4" Grid.Column="1" Maximum="1" Minimum="0" ValueChanged="OnTrianglePointsChanged" />

<Label FontSize="24" Text="Point C" Grid.Row="5" Grid.ColumnSpan="2" />
<Slider x:Name="PointCX" Grid.Row="6" Grid.Column="0" Maximum="1" Minimum="0" ValueChanged="OnTrianglePointsChanged" />
<Slider x:Name="PointCY" Grid.Row="6" Grid.Column="1" Maximum="1" Minimum="0" ValueChanged="OnTrianglePointsChanged" />
<Label Grid.Row="0" Grid.Column="0" FontSize="24" Text="X" />
<Label Grid.Row="0" Grid.Column="1" FontSize="24" Text="Y" />

<Label Grid.Row="1" Grid.ColumnSpan="2" FontSize="24" Text="Point A" />
<Slider
x:Name="PointAX"
Grid.Row="2"
Grid.Column="0"
Maximum="1"
Minimum="0"
ValueChanged="OnTrianglePointsChanged" />
<Slider
x:Name="PointAY"
Grid.Row="2"
Grid.Column="1"
Maximum="1"
Minimum="0"
ValueChanged="OnTrianglePointsChanged" />

<Label Grid.Row="3" Grid.ColumnSpan="2" FontSize="24" Text="Point B" />
<Slider
x:Name="PointBX"
Grid.Row="4"
Grid.Column="0"
Maximum="1"
Minimum="0"
ValueChanged="OnTrianglePointsChanged" />
<Slider
x:Name="PointBY"
Grid.Row="4"
Grid.Column="1"
Maximum="1"
Minimum="0"
ValueChanged="OnTrianglePointsChanged" />

<Label Grid.Row="5" Grid.ColumnSpan="2" FontSize="24" Text="Point C" />
<Slider
x:Name="PointCX"
Grid.Row="6"
Grid.Column="0"
Maximum="1"
Minimum="0"
ValueChanged="OnTrianglePointsChanged" />
<Slider
x:Name="PointCY"
Grid.Row="6"
Grid.Column="1"
Maximum="1"
Minimum="0"
ValueChanged="OnTrianglePointsChanged" />
</Grid>

<background:MaterialShapeView x:Name="ShapeView" HeightRequest="200" HorizontalOptions="FillAndExpand">
Expand Down
3 changes: 3 additions & 0 deletions src/XamarinBackgroundKitSample/ShapeExplorerPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ private void UpdateShape()
case "Rect":
ShapeView.Shape = new Rect();
break;
case "Circle":
ShapeView.Shape = new Circle();
break;
case "RoundRect":
ShapeView.Shape = new RoundRect();
CornerRadiusConfigContainer.IsVisible = true;
Expand Down

0 comments on commit 556f26e

Please sign in to comment.