This repository was archived by the owner on May 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 459
CornerRadiusEffect #1316
Merged
TheCodeTraveler
merged 17 commits into
xamarin:develop
from
YZahringer:corner-radius-effect
Nov 11, 2021
Merged
CornerRadiusEffect #1316
Changes from 13 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
a471a8c
CornerRadiusEffect added
YZahringer bec5929
cosmetics
YZahringer fc60faa
Safe corner radius value impl
YZahringer fa6b679
nullable fix
YZahringer f383769
Merge branch 'develop' into corner-radius-effect
jsuarezruiz 9e3db81
reduce to one linq call
YZahringer e58a991
Merge branch 'develop' into corner-radius-effect
pictos 522a7a2
Effect replaced by event subscription
YZahringer 9eb7752
Update src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/CornerRa…
pictos 13729a3
C#9 cleanup
YZahringer 89b980b
removed extra )
pictos 19101c4
Merge branch 'develop' into corner-radius-effect
pictos a968a95
Merge branch 'develop' into corner-radius-effect
pictos 22a714d
Update src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/CornerRa…
pictos 483a69d
Merge branch 'develop' into corner-radius-effect
pictos 794b591
Merge branch 'develop' into corner-radius-effect
AndreiMisiukevich b921162
Merge branch 'develop' into corner-radius-effect
TheCodeTraveler File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
137 changes: 137 additions & 0 deletions
137
samples/XCT.Sample/Pages/Effects/CornerRadiusEffectPage.xaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<pages:BasePage | ||
x:Class="Xamarin.CommunityToolkit.Sample.Pages.Effects.CornerRadiusEffectPage" | ||
xmlns="http://xamarin.com/schemas/2014/forms" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
xmlns:pages="clr-namespace:Xamarin.CommunityToolkit.Sample.Pages" | ||
xmlns:xct="http://xamarin.com/schemas/2020/toolkit" | ||
x:Name="Page"> | ||
|
||
<pages:BasePage.Resources> | ||
<ResourceDictionary> | ||
<Style TargetType="Slider"> | ||
<Setter Property="MaximumTrackColor" Value="White" /> | ||
<Setter Property="ThumbColor" Value="Blue" /> | ||
</Style> | ||
<Style TargetType="Label"> | ||
<Setter Property="LineBreakMode" Value="TailTruncation" /> | ||
</Style> | ||
</ResourceDictionary> | ||
</pages:BasePage.Resources> | ||
|
||
<ScrollView> | ||
<Grid RowDefinitions="*,Auto"> | ||
<Grid Grid.Row="0"> | ||
<ContentView | ||
Grid.Row="0" | ||
xct:CornerRadiusEffect.CornerRadius="{Binding CornerRadius, Source={x:Reference Page}}" | ||
BackgroundColor="Blue" | ||
HeightRequest="{Binding Value, Source={x:Reference Name=SliderHeight}}" | ||
HorizontalOptions="Center" | ||
VerticalOptions="Center" | ||
WidthRequest="{Binding Value, Source={x:Reference Name=SliderWidth}}" /> | ||
</Grid> | ||
|
||
<Grid | ||
Grid.Row="1" | ||
Padding="10" | ||
BackgroundColor="LightGray" | ||
RowSpacing="0"> | ||
<Grid.RowDefinitions> | ||
<RowDefinition Height="Auto" /> | ||
<RowDefinition Height="Auto" /> | ||
<RowDefinition Height="Auto" /> | ||
<RowDefinition Height="Auto" /> | ||
<RowDefinition Height="Auto" /> | ||
<RowDefinition Height="Auto" /> | ||
</Grid.RowDefinitions> | ||
<Grid.ColumnDefinitions> | ||
<ColumnDefinition Width="*" /> | ||
<ColumnDefinition Width="Auto" /> | ||
<ColumnDefinition Width="100" /> | ||
<ColumnDefinition Width="Auto" /> | ||
<ColumnDefinition Width="100" /> | ||
<ColumnDefinition Width="*" /> | ||
</Grid.ColumnDefinitions> | ||
|
||
<Label | ||
Grid.Row="0" | ||
Grid.Column="1" | ||
HorizontalOptions="End" | ||
Text="Width" /> | ||
<Slider | ||
x:Name="SliderWidth" | ||
Grid.Row="0" | ||
Grid.Column="2" | ||
Maximum="1000" | ||
Minimum="100" | ||
Value="100" /> | ||
|
||
<Label | ||
Grid.Row="0" | ||
Grid.Column="3" | ||
HorizontalOptions="End" | ||
Text="Height" /> | ||
<Slider | ||
x:Name="SliderHeight" | ||
Grid.Row="0" | ||
Grid.Column="4" | ||
Maximum="1000" | ||
Minimum="100" | ||
Value="100" /> | ||
|
||
<Label | ||
Grid.Row="1" | ||
Grid.Column="1" | ||
HorizontalOptions="End" | ||
Text="TopLeft" /> | ||
<Slider | ||
x:Name="SliderCornerRadiusTopLeft" | ||
Grid.Row="1" | ||
Grid.Column="2" | ||
Maximum="200" | ||
Minimum="0" | ||
Value="10" /> | ||
|
||
<Label | ||
Grid.Row="1" | ||
Grid.Column="3" | ||
HorizontalOptions="End" | ||
Text="TopRight" /> | ||
<Slider | ||
x:Name="SliderCornerRadiusTopRight" | ||
Grid.Row="1" | ||
Grid.Column="4" | ||
Maximum="200" | ||
Minimum="0" | ||
Value="10" /> | ||
|
||
<Label | ||
Grid.Row="2" | ||
Grid.Column="1" | ||
HorizontalOptions="End" | ||
Text="BottomLeft" /> | ||
<Slider | ||
x:Name="SliderCornerRadiusBottomLeft" | ||
Grid.Row="2" | ||
Grid.Column="2" | ||
Maximum="200" | ||
Minimum="0" | ||
Value="10" /> | ||
|
||
<Label | ||
Grid.Row="2" | ||
Grid.Column="3" | ||
HorizontalOptions="End" | ||
Text="BottomRight" /> | ||
<Slider | ||
x:Name="SliderCornerRadiusBottomRight" | ||
Grid.Row="2" | ||
Grid.Column="4" | ||
Maximum="200" | ||
Minimum="0" | ||
Value="10" /> | ||
</Grid> | ||
</Grid> | ||
</ScrollView> | ||
</pages:BasePage> |
27 changes: 27 additions & 0 deletions
27
samples/XCT.Sample/Pages/Effects/CornerRadiusEffectPage.xaml.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using Xamarin.Forms; | ||
|
||
namespace Xamarin.CommunityToolkit.Sample.Pages.Effects | ||
{ | ||
public partial class CornerRadiusEffectPage | ||
{ | ||
public CornerRadiusEffectPage() | ||
{ | ||
InitializeComponent(); | ||
|
||
SliderCornerRadiusTopLeft.ValueChanged += OnCornerRadiusValueChanged; | ||
SliderCornerRadiusTopRight.ValueChanged += OnCornerRadiusValueChanged; | ||
SliderCornerRadiusBottomLeft.ValueChanged += OnCornerRadiusValueChanged; | ||
SliderCornerRadiusBottomRight.ValueChanged += OnCornerRadiusValueChanged; | ||
} | ||
|
||
void OnCornerRadiusValueChanged(object sender, ValueChangedEventArgs e) | ||
{ | ||
CornerRadius = new CornerRadius( | ||
SliderCornerRadiusTopLeft.Value, SliderCornerRadiusTopRight.Value, | ||
SliderCornerRadiusBottomLeft.Value, SliderCornerRadiusBottomRight.Value); | ||
OnPropertyChanged(nameof(CornerRadius)); | ||
} | ||
|
||
public CornerRadius CornerRadius { get; private set; } = new (10); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
...mmunityToolkit/Xamarin.CommunityToolkit/Effects/CornerRadius/CornerRadiusEffect.shared.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
using System; | ||
using Xamarin.Forms; | ||
using Xamarin.Forms.Shapes; | ||
|
||
namespace Xamarin.CommunityToolkit.Effects | ||
{ | ||
public class CornerRadiusEffect | ||
{ | ||
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.CreateAttached( | ||
nameof(CornerRadius), | ||
typeof(CornerRadius), | ||
typeof(CornerRadiusEffect), | ||
default(CornerRadius), | ||
propertyChanged: OnCornerRadiusPropertyChanged); | ||
|
||
static void OnCornerRadiusPropertyChanged(BindableObject bindable, object oldValue, object newValue) | ||
{ | ||
if (bindable is not VisualElement elementView) | ||
return; | ||
|
||
elementView.SizeChanged -= ElementViewSizeChanged; | ||
elementView.SizeChanged += ElementViewSizeChanged; | ||
|
||
UpdateClip(elementView); | ||
} | ||
|
||
static void ElementViewSizeChanged(object? sender, EventArgs e) | ||
{ | ||
if (sender is not VisualElement elementView) | ||
return; | ||
|
||
UpdateClip(elementView); | ||
pictos marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
public static CornerRadius GetCornerRadius(BindableObject? bindable) | ||
=> (CornerRadius)(bindable?.GetValue(CornerRadiusProperty) ?? throw new ArgumentNullException(nameof(bindable))); | ||
|
||
public static void SetCornerRadius(BindableObject? bindable, CornerRadius value) | ||
=> bindable?.SetValue(CornerRadiusProperty, value); | ||
|
||
static void UpdateClip(VisualElement elementView) | ||
{ | ||
var rect = new Rect(0, 0, elementView.Width, elementView.Height); | ||
var cornerRadius = GetCornerRadius(rect, elementView); | ||
if (cornerRadius == default) | ||
{ | ||
elementView.Clip = null; | ||
return; | ||
} | ||
|
||
if (elementView.Clip is not RoundRectangleGeometry roundRectangleGeometry) | ||
{ | ||
elementView.Clip = new RoundRectangleGeometry(cornerRadius, rect); | ||
return; | ||
} | ||
|
||
roundRectangleGeometry.CornerRadius = cornerRadius; | ||
roundRectangleGeometry.Rect = rect; | ||
} | ||
|
||
static CornerRadius GetCornerRadius(Rect rect, VisualElement elementView) | ||
{ | ||
var maxCornerRadius = Math.Min(rect.Width, rect.Height) / 2; | ||
if (maxCornerRadius <= 0) | ||
return default; | ||
|
||
var cornerRadius = GetCornerRadius(elementView); | ||
if (cornerRadius.TopLeft > maxCornerRadius || | ||
cornerRadius.TopRight > maxCornerRadius || | ||
cornerRadius.BottomLeft > maxCornerRadius || | ||
cornerRadius.BottomRight > maxCornerRadius) | ||
{ | ||
return new CornerRadius( | ||
Math.Min(cornerRadius.TopLeft, maxCornerRadius), | ||
Math.Min(cornerRadius.TopRight, maxCornerRadius), | ||
Math.Min(cornerRadius.BottomLeft, maxCornerRadius), | ||
Math.Min(cornerRadius.BottomRight, maxCornerRadius)); | ||
} | ||
|
||
return cornerRadius; | ||
} | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to point out, that we need to see if this will not cause a memory leak. I believe that doesn't, but just want to make sure to bring more eyes to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we don't unsubscribe from the event as there is no detach method. Maybe use WeakEventManager?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if we can use the WeakEventManager to subscribe to other events. I'll confirm if this can be an issue, if so I'll implement a fix during this week (;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, unfortunately the current implementation of
WeakEventManager
does not support subscription to other events.Maybe an enhancement that could be added, like with WPF: https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/weak-event-patterns?view=netframeworkdesktop-4.8#using-an-existing-weak-event-manager-class
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like this idea. @brminnick do you think that could be added on WeakEventManager or would be better to have this as a separated internal feature?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting! @YZahringer is there an open Issue for it? If not, could you create one, tag me in it, and I'll take a look!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Taking this old MS app as a reference it's ok to use this approach. I think that we're good to go