Skip to content

Commit 566ca6d

Browse files
cleaner api
1 parent b511f4b commit 566ca6d

File tree

5 files changed

+177
-59
lines changed

5 files changed

+177
-59
lines changed

samples/Views/PlaylistTransitionView.cs

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,30 +34,70 @@ public PlaylistTransitionView()
3434
var t2 = 100;
3535

3636
HasTransitionState<PlaylistCollection>(
37-
_root.Flows().ToDouble(HeightRequestProperty, 500).ToDouble(MaximumWidthRequestProperty, 600),
38-
_backButton.Flows().ToDouble(OpacityProperty, 0),
39-
_avatar.Flows().ToMargin(top: t1, left: l1).ToLayoutBounds(0, 0),
40-
_nameLabel.Flows().ToMargin(top: t1 + 5, left: l2).ToLayoutBounds(0, 0),
41-
_dateLabel.Flows().ToMargin(top: t1 + 30, left: l2).ToLayoutBounds(0, 0),
42-
_addButton.Flows().ToMargin(top: t1, right: r1).ToDouble(ScaleProperty, 1).ToLayoutBounds(1, 0),
43-
_playlistNameLabel.Flows().ToMargin(top: t2).ToDouble(ScaleProperty, 1).ToLayoutBounds(0.5, 0),
44-
_dataLayout.Flows().ToMargin(top: t2 + 60).ToLayoutBounds(0.5, 0),
45-
_descriptionLabel.Flows().ToDouble(OpacityProperty, 0),
46-
_downloadButton.Flows().ToDouble(OpacityProperty, 0),
47-
_moreButton.Flows().ToDouble(OpacityProperty, 0));
37+
_root.Flows(
38+
(HeightRequestProperty, 500),
39+
(MaximumWidthRequestProperty, 600)),
40+
_backButton.Flows(
41+
(OpacityProperty, 0)),
42+
_avatar.Flows(
43+
(MarginProperty, new Thickness(l1, t1, 0, 0)),
44+
(AbsoluteLayout.LayoutBoundsProperty, new Point(0, 0))),
45+
_nameLabel.Flows(
46+
(MarginProperty, new Thickness(l2, t1 + 5, 0, 0)),
47+
(AbsoluteLayout.LayoutBoundsProperty, new Point(0, 0))),
48+
_dateLabel.Flows(
49+
(MarginProperty, new Thickness(l2, t1 + 30, 0, 0)),
50+
(AbsoluteLayout.LayoutBoundsProperty, new Point(0, 0))),
51+
_addButton.Flows(
52+
(MarginProperty, new Thickness(0, t1, r1, 0)),
53+
(ScaleProperty, 1),
54+
(AbsoluteLayout.LayoutBoundsProperty, new Point(1, 0))),
55+
_playlistNameLabel.Flows(
56+
(MarginProperty, new Thickness(0, t2, 0, 0)),
57+
(ScaleProperty, 1),
58+
(AbsoluteLayout.LayoutBoundsProperty, new Point(0.5, 0))),
59+
_dataLayout.Flows(
60+
(MarginProperty, new Thickness(0, t2 + 60, 0, 0)),
61+
(AbsoluteLayout.LayoutBoundsProperty, new Point(0.5, 0))),
62+
_descriptionLabel.Flows(
63+
(OpacityProperty, 0)),
64+
_downloadButton.Flows(
65+
(OpacityProperty, 0)),
66+
_moreButton.Flows(
67+
(OpacityProperty, 0)));
4868

4969
HasTransitionState<Playlist>(
50-
_root.Flows().ToDouble(HeightRequestProperty, 650).ToDouble(MaximumWidthRequestProperty, 2000),
51-
_backButton.Flows().ToDouble(OpacityProperty, 1),
52-
_avatar.Flows().ToMargin(top: t1).ToLayoutBounds(0.5, 0),
53-
_nameLabel.Flows().ToMargin(top: t2).ToLayoutBounds(0.5, 0),
54-
_dateLabel.Flows().ToMargin(top: t2 + 25).ToLayoutBounds(0.5, 0),
55-
_addButton.Flows().ToMargin(top: 50, left: 25).ToDouble(ScaleProperty, 0.5).ToLayoutBounds(0.5, 0),
56-
_playlistNameLabel.Flows().ToMargin(top: t2 + 60).ToDouble(ScaleProperty, 1.5).ToLayoutBounds(0.5, 0),
57-
_dataLayout.Flows().ToMargin(top: t2 + 120).ToLayoutBounds(0.5, 0),
58-
_descriptionLabel.Flows().ToMargin(top: 20).ToDouble(OpacityProperty, 1),
59-
_downloadButton.Flows().ToDouble(OpacityProperty, 1),
60-
_moreButton.Flows().ToDouble(OpacityProperty, 1));
70+
_root.Flows(
71+
(HeightRequestProperty, 650),
72+
(MaximumWidthRequestProperty, 2000)),
73+
_backButton.Flows(
74+
(OpacityProperty, 1)),
75+
_avatar.Flows(
76+
(MarginProperty, new Thickness(0, t1, 0, 0)),
77+
(AbsoluteLayout.LayoutBoundsProperty, new Point(0.5, 0))),
78+
_nameLabel.Flows(
79+
(MarginProperty, new Thickness(0, t2, 0, 0)),
80+
(AbsoluteLayout.LayoutBoundsProperty, new Point(0.5, 0))),
81+
_dateLabel.Flows(
82+
(MarginProperty, new Thickness(0, t2 + 25, 0, 0)),
83+
(AbsoluteLayout.LayoutBoundsProperty, new Point(0.5, 0))),
84+
_addButton.Flows(
85+
(MarginProperty, new Thickness(25, 50, 0, 0)),
86+
(ScaleProperty, 0.5),
87+
(AbsoluteLayout.LayoutBoundsProperty, new Point(0.5, 0))),
88+
_playlistNameLabel.Flows(
89+
(MarginProperty, new Thickness(0, t2 + 60, 0, 0)),
90+
(ScaleProperty, 1.5),
91+
(AbsoluteLayout.LayoutBoundsProperty, new Point(0.5, 0))),
92+
_dataLayout.Flows(
93+
(MarginProperty, new Thickness(0, t2 + 120, 0, 0)),
94+
(AbsoluteLayout.LayoutBoundsProperty, new Point(0.5, 0))),
95+
_descriptionLabel.Flows(
96+
(OpacityProperty, 1)),
97+
_downloadButton.Flows(
98+
(OpacityProperty, 1)),
99+
_moreButton.Flows(
100+
(OpacityProperty, 1)));
61101
}
62102

63103
public Style<Button> ButtonStyle => new Style<Button>()

src/FlowNavigation.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ private async Task<View> Go(bool isHotReload = false)
159159
{
160160
var tb = _activeView.TransitionView.TransitionBounds;
161161

162-
_ = ((View)_activeView).Flow(v => v.Flows()
162+
_ = ((View)_activeView).Animate(v => v.Flows()
163163
.ToDouble(VisualElement.TranslationXProperty, tb.Left)
164164
.ToDouble(VisualElement.TranslationYProperty, tb.Top)
165165
.ToDouble(VisualElement.WidthRequestProperty, tb.Width)
@@ -199,7 +199,7 @@ private async Task<View> Go(bool isHotReload = false)
199199

200200
var flowView = (Page?)Current?.View ?? throw new Exception("unable to get current view.");
201201

202-
_ = nextView.Flow(v => v.Flows()
202+
_ = nextView.Animate(v => v.Flows()
203203
.ToDouble(VisualElement.TranslationXProperty, 0)
204204
.ToDouble(VisualElement.TranslationYProperty, 0)
205205
.ToDouble(VisualElement.WidthRequestProperty, flowView.Width)

src/Flowing/Flow.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
namespace FluidNav.Flowing;
44

5-
public class Flow(VisualElement visual) : IEnumerable<FlowProperty>
5+
public class Flow(View view) : IEnumerable<FlowProperty>
66
{
77
private readonly List<FlowProperty> _flowProperties = [];
88

9-
public VisualElement VisualElement { get; } = visual;
9+
public View View { get; } = view;
1010

1111
public Flow Add(FlowProperty flowProperty)
1212
{

src/Flowing/FluidAnimationsExtensions.cs

Lines changed: 107 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,62 @@
22

33
public static class FluidAnimationsExtensions
44
{
5-
public static Flow Flows(this VisualElement element, params (BindableProperty, object value)[] values)
5+
/// <summary>
6+
/// Defines the flow properties for the given view.
7+
/// </summary>
8+
/// <param name="view">the view.</param>
9+
/// <param name="values">The property/value pair.</param>
10+
/// <returns>da flow.</returns>
11+
public static Flow Flows(this View view, params (BindableProperty, object value)[] values)
612
{
7-
var flow = new Flow(element);
13+
var flow = new Flow(view);
814

915
foreach (var (property, value) in values)
1016
{
1117
if (property.ReturnType == typeof(double))
12-
_ = flow.ToDouble(property, (double)value);
18+
{
19+
_ = flow.ToDouble(property, Convert.ToDouble(value));
20+
}
1321
else if (property.ReturnType == typeof(Thickness))
14-
_ = flow.ToThickness(property, (Thickness)value);
22+
{
23+
_ = value.IsNumber()
24+
? flow.ToThickness(property, new Thickness(Convert.ToDouble(value)))
25+
: flow.ToThickness(property, (Thickness)value);
26+
}
1527
else if (property.ReturnType == typeof(Color))
28+
{
1629
_ = flow.ToColor(property, (Color)value);
17-
else if (property.ReturnType == typeof(Rect))
18-
_ = flow.ToLayoutBounds(((Rect)value).X, ((Rect)value).Y, ((Rect)value).Width, ((Rect)value).Height);
30+
}
31+
else if (property == AbsoluteLayout.LayoutBoundsProperty)
32+
{
33+
#pragma warning disable IDE0045 // Convert to conditional expression
34+
if (value is Rect rect)
35+
{
36+
_ = flow.ToLayoutBounds(((Rect)value).X, ((Rect)value).Y, ((Rect)value).Width, ((Rect)value).Height);
37+
}
38+
else if (value is Point point)
39+
{
40+
_ = flow.ToLayoutBounds(((Point)value).X, ((Point)value).Y);
41+
}
42+
else
43+
{
44+
throw new ArgumentException(
45+
$"The given type is not supported for the LayoutBoundsProperty property");
46+
}
47+
#pragma warning restore IDE0045 // Convert to conditional expression
48+
}
1949
else
20-
throw new ArgumentException(
21-
"Property flow error. Property must be of type double, Thickness, Color or Rect", nameof(property));
50+
{
51+
throw new ArgumentException($"The given type is not supported.", nameof(property));
52+
}
2253
}
2354

2455
return flow;
2556
}
2657

27-
public static Flow Flows(this VisualElement element)
58+
public static Flow Flows(this View view)
2859
{
29-
return new Flow(element);
60+
return new Flow(view);
3061
}
3162

3263
public static Flow ToDouble(
@@ -35,16 +66,16 @@ public static Flow ToDouble(
3566
if (property.ReturnType != typeof(double))
3667
throw new ArgumentException("Property flow error. Property must be of type double", nameof(property));
3768

38-
var a = (double)flow.VisualElement.GetValue(property);
69+
var a = (double)flow.View.GetValue(property);
3970

4071
return flow.Add(
4172
new FlowProperty(
42-
flow.VisualElement,
73+
flow.View,
4374
property,
4475
value,
4576
() =>
4677
{
47-
var start = (double)flow.VisualElement.GetValue(property);
78+
var start = (double)flow.View.GetValue(property);
4879
return t => start + t * (value - start);
4980
},
5081
start,
@@ -66,17 +97,19 @@ public static Flow ToThickness(
6697
public static Flow ToThickness(
6798
this Flow flow, BindableProperty property, Thickness value, double start = 0, double end = 1)
6899
{
100+
#pragma warning disable IDE0046 // Convert to conditional expression
69101
if (property.ReturnType != typeof(Thickness))
70102
throw new ArgumentException("Property flow error. Property must be of type Thickness", nameof(property));
103+
#pragma warning restore IDE0046 // Convert to conditional expression
71104

72105
return flow.Add(
73106
new FlowProperty(
74-
flow.VisualElement,
107+
flow.View,
75108
property,
76109
value,
77110
() =>
78111
{
79-
var start = (Thickness)flow.VisualElement.GetValue(property);
112+
var start = (Thickness)flow.View.GetValue(property);
80113
return t => new Thickness(
81114
start.Left + t * (value.Left - start.Left),
82115
start.Top + t * (value.Top - start.Top),
@@ -90,17 +123,19 @@ public static Flow ToThickness(
90123
public static Flow ToColor(
91124
this Flow flow, BindableProperty property, Color color, double start = 0, double end = 1)
92125
{
126+
#pragma warning disable IDE0046 // Convert to conditional expression
93127
if (property.ReturnType != typeof(Color))
94128
throw new ArgumentException("Property flow error. Property must be of type Color", nameof(property));
129+
#pragma warning restore IDE0046 // Convert to conditional expression
95130

96131
return flow.Add(
97132
new FlowProperty(
98-
flow.VisualElement,
133+
flow.View,
99134
property,
100135
color,
101136
() =>
102137
{
103-
var start = (Color)flow.VisualElement.GetValue(property);
138+
var start = (Color)flow.View.GetValue(property);
104139
return t => Color.FromRgba(
105140
start.Red + t * (color.Red - start.Red),
106141
start.Green + t * (color.Green - start.Green),
@@ -122,12 +157,12 @@ public static Flow ToLayoutBounds(
122157
{
123158
return flow.Add(
124159
new FlowProperty(
125-
flow.VisualElement,
160+
flow.View,
126161
AbsoluteLayout.LayoutBoundsProperty,
127162
new Rect(x, y, width, height),
128163
() =>
129164
{
130-
var start = (Rect)flow.VisualElement.GetValue(AbsoluteLayout.LayoutBoundsProperty);
165+
var start = (Rect)flow.View.GetValue(AbsoluteLayout.LayoutBoundsProperty);
131166
return t => new Rect(
132167
start.X + t * (x - start.X),
133168
start.Y + t * (y - start.Y),
@@ -144,9 +179,9 @@ public static Flow ToLayoutBounds(
144179
/// <param name="view">The target view.</param>
145180
/// <param name="flowBuilder">da flow builder.</param>
146181
/// <returns></returns>
147-
public static T FlowToResult<T>(this T view, Func<T, IEnumerable<Flow>> flowBuilder) where T : View
182+
public static T Complete<T>(this T view, Func<T, IEnumerable<Flow>> flowBuilder) where T : View
148183
{
149-
return view.FlowToResult(flowBuilder(view));
184+
return view.Complete(flowBuilder(view));
150185
}
151186

152187
/// <summary>
@@ -155,9 +190,19 @@ public static T FlowToResult<T>(this T view, Func<T, IEnumerable<Flow>> flowBuil
155190
/// <param name="view">The target view.</param>
156191
/// <param name="flowBuilder">da flow builder.</param>
157192
/// <returns></returns>
158-
public static T FlowToResult<T>(this T view, Func<T, Flow> flowBuilder) where T : View
193+
public static T Complete<T>(this T view, Func<T, Flow> flowBuilder) where T : View
194+
{
195+
return view.Complete([flowBuilder(view)]);
196+
}
197+
198+
/// <summary>
199+
/// Sets all the flow properties to their target values (without animations).
200+
/// </summary>
201+
/// <param name="flow">da flow.</param>
202+
/// <returns></returns>
203+
public static T Complete<T>(this Flow flow) where T : View
159204
{
160-
return view.FlowToResult([flowBuilder(view)]);
205+
return (T)flow.View.Complete([flow]);
161206
}
162207

163208
/// <summary>
@@ -166,7 +211,7 @@ public static T FlowToResult<T>(this T view, Func<T, Flow> flowBuilder) where T
166211
/// <param name="view">The target view.</param>
167212
/// <param name="flowCollection">da flow.</param>
168213
/// <returns></returns>
169-
public static T FlowToResult<T>(this T view, IEnumerable<Flow> flowCollection) where T : View
214+
public static T Complete<T>(this T view, IEnumerable<Flow> flowCollection) where T : View
170215
{
171216
foreach (var flow in flowCollection)
172217
foreach (var flowProperty in flow)
@@ -186,12 +231,12 @@ public static T FlowToResult<T>(this T view, IEnumerable<Flow> flowCollection) w
186231
/// <param name="fps">Frames per second, default is 60.</param>
187232
/// <param name="animationName">The animation identifier name, by default a new Guid is used.</param>
188233
/// <returns>A task that completes when the animations ends.</returns>
189-
public static Task<bool> Flow<T>(
234+
public static Task<bool> Animate<T>(
190235
this T view, Func<T, IEnumerable<Flow>> flowBuilder, VisualElement? owner = null, uint duration = 500,
191236
Easing? easing = null, uint fps = 60, string? animationName = null)
192237
where T : View
193238
{
194-
return view.Flow(flowBuilder(view), owner, duration, easing, fps, animationName);
239+
return view.Animate(flowBuilder(view), owner, duration, easing, fps, animationName);
195240
}
196241

197242
/// <summary>
@@ -205,12 +250,30 @@ public static Task<bool> Flow<T>(
205250
/// <param name="fps">Frames per second, default is 60.</param>
206251
/// <param name="animationName">The animation identifier name, by default a new Guid is used.</param>
207252
/// <returns>A task that completes when the animations ends.</returns>
208-
public static Task<bool> Flow<T>(
253+
public static Task<bool> Animate<T>(
209254
this T view, Func<T, Flow> flowBuilder, VisualElement? owner = null, uint duration = 500,
210255
Easing? easing = null, uint fps = 60, string? animationName = null)
211256
where T : View
212257
{
213-
return view.Flow([flowBuilder(view)], owner, duration, easing, fps, animationName);
258+
return view.Animate([flowBuilder(view)], owner, duration, easing, fps, animationName);
259+
}
260+
261+
/// <summary>
262+
/// Starts a flow animation and returns a task that completes when the animation ends.
263+
/// </summary>
264+
/// <param name="flow">da flow.</param>
265+
/// <param name="owner">Identifies the owner of the animation. This can be the visual element on which the animation is applied, or another visual element, such as the page</param>
266+
/// <param name="duration">The duration in milliseconds.</param>
267+
/// <param name="easing">The easing function.</param>
268+
/// <param name="fps">Frames per second, default is 60.</param>
269+
/// <param name="animationName">The animation identifier name, by default a new Guid is used.</param>
270+
/// <returns>A task that completes when the animations ends.</returns>
271+
public static Task<bool> Animate<T>(
272+
this Flow flow, VisualElement? owner = null, uint duration = 500,
273+
Easing? easing = null, uint fps = 60, string? animationName = null)
274+
where T : View
275+
{
276+
return flow.View.Animate([flow], owner, duration, easing, fps, animationName);
214277
}
215278

216279
/// <summary>
@@ -224,7 +287,7 @@ public static Task<bool> Flow<T>(
224287
/// <param name="fps">Frames per second, default is 60.</param>
225288
/// <param name="animationName">The animation identifier name, by default a new Guid is used.</param>
226289
/// <returns>A task that completes when the animations ends.</returns>
227-
public static Task<bool> Flow(
290+
public static Task<bool> Animate(
228291
this View view, IEnumerable<Flow> flowCollection, VisualElement? owner = null, uint duration = 500,
229292
Easing? easing = null, uint fps = 60, string? animationName = null)
230293
{
@@ -249,4 +312,19 @@ public static Task<bool> Flow(
249312

250313
return taskCompletionSource.Task;
251314
}
315+
316+
private static bool IsNumber(this object value)
317+
{
318+
return value is sbyte
319+
or byte
320+
or short
321+
or ushort
322+
or int
323+
or uint
324+
or long
325+
or ulong
326+
or float
327+
or double
328+
or decimal;
329+
}
252330
}

0 commit comments

Comments
 (0)