Skip to content

Commit 4a2fb11

Browse files
authored
Merge pull request #16 from xtuzy/Modify
main work is optimize animation
2 parents 5a1dbad + 56ac375 commit 4a2fb11

File tree

6 files changed

+162
-70
lines changed

6 files changed

+162
-70
lines changed

SharpConstraintLayout.Maui.Example/Pages/ShowAnimationView.xaml.cs

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ public ShowAnimationView()
4545
private void Button2_Clicked(object sender, EventArgs e)
4646
{
4747
#if WINDOWS|| __ANDROID__||__IOS__
48-
/*if (_frameRateCalculateTimer == null)
49-
FrameRate();*/
5048
if (fr == null)
5149
{
5250
fr = new BlogFrameRate.FrameRateCalculator();
@@ -58,26 +56,47 @@ private void Button2_Clicked(object sender, EventArgs e)
5856
}
5957
#endif
6058
layout.AbortAnimation("ConstrainTo");
61-
//layout.AbortAnimation("ConstrainTo");
6259
if (isExpaned)//ÐèÒªÊÕËõ
6360
{
64-
var finish = new FluentConstraintSet();
65-
finish.Clone(layout);
66-
finish.Select(backgroundView).Clear().TopToTop().LeftToLeft().Height(50).MinHeight(20).Width(SizeBehavier.MatchParent)
61+
var beginState = new FluentConstraintSet();
62+
beginState.Clone(layout);
63+
64+
var button1FinishState = new FluentConstraintSet();
65+
button1FinishState.Clone(layout);
66+
button1FinishState.Select(button1).Clear().CenterYTo().RightToRight();
67+
68+
var button23FinishState = new FluentConstraintSet();
69+
button23FinishState.Clone(layout);
70+
button23FinishState.Select(backgroundView).Clear().TopToTop().LeftToLeft().Height(50).MinHeight(20).Width(SizeBehavier.MatchParent)
6771
.Select(button2).Clear().BottomToBottom(null, 20).RightToRight(null, 20)
6872
.Select(button3).Clear().CenterYTo(button2).RightToLeft(button2, 50).Rotation(-90).Scale(2).Alpha(0.3f)
6973
;
70-
layout.LayoutToWithAnim(finish, "ConstrainTo", 16, 1200, Easing.SpringOut);
74+
75+
var button1Anim = layout.CreateAnimation(beginState, button1FinishState, Easing.Linear);
76+
77+
var button2Anim = layout.CreateAnimation(beginState, button23FinishState, Easing.Linear);
78+
79+
var allAnim = new Animation()
80+
{
81+
{ 0, 1, button2Anim },
82+
{ 0.5, 1, button1Anim }
83+
};
84+
allAnim.Commit(layout, "ConstrainTo", 16, 3000, Easing.Linear, (v, b) =>
85+
{
86+
//When finish,we need combine all button state
87+
button23FinishState.Clone(new KeyValuePair<int, ConstraintSet.Constraint>(button1.GetId(), button1FinishState.GetConstraint(button1.GetId())));
88+
button23FinishState.ApplyTo(layout);
89+
});
7190
}
7291
else
7392
{
74-
var start = new FluentConstraintSet();
75-
start.Clone(layout);
76-
start.Select(backgroundView).Clear().TopToTop().EdgesXTo().Width(SizeBehavier.MatchConstraint).PercentHeight(0.5f).Height(SizeBehavier.MatchConstraint)
93+
var button23FinishState = new FluentConstraintSet();
94+
button23FinishState.Clone(layout);
95+
button23FinishState.Select(backgroundView).Clear().TopToTop().EdgesXTo().Width(SizeBehavier.MatchConstraint).PercentHeight(0.5f).Height(SizeBehavier.MatchConstraint)
7796
.Select(button2).Clear().BottomToBottom(backgroundView, 20).RightToRight(backgroundView, 20)
7897
.Select(button3).Clear().BottomToTop(button2, 20).CenterXTo(button2).Rotation(0)
7998
;
80-
layout.LayoutToWithAnim(start, "ConstrainTo", 8, 3000, Easing.SpringOut);
99+
layout.LayoutToWithAnim(button23FinishState, "ConstrainTo", 16, 3000, Easing.SpringOut);
81100
}
82101
isExpaned = !isExpaned;
83102
}
@@ -92,35 +111,5 @@ private void Button1_Clicked(object sender, EventArgs e)
92111
finish.Select(button1).Clear().CenterYTo().RightToRight();
93112
layout.LayoutToWithAnim(finish, "ConstrainTo", 16, 1200, Easing.SpringOut, (v, b) => { start.ApplyTo(layout); });
94113
}
95-
#if WINDOWS
96-
private uint _counter = 0;
97-
private uint _previousCounter = 0;
98-
private readonly Stopwatch _frameRateStopwatch = new Stopwatch();
99-
private readonly Timer _frameRateCalculateTimer;
100-
void FrameRate()
101-
{
102-
103-
var _frameRateCalculateTimer = new Timer(CalculateFrameRate);
104-
_frameRateStopwatch.Start();
105-
_frameRateCalculateTimer.Change(1000, 1000);
106-
Microsoft.UI.Xaml.Media.CompositionTarget.Rendering += CompositionTarget_Rendering;
107-
108-
}
109-
110-
private void CompositionTarget_Rendering(object sender, object e)
111-
{
112-
_counter++;
113-
}
114-
115-
private void CalculateFrameRate(object state)
116-
{
117-
var frameCount = _counter - _previousCounter;
118-
_previousCounter = _counter;
119-
var fps = ((double)frameCount / _frameRateStopwatch.ElapsedMilliseconds) * 1000;
120-
System.Diagnostics.Debug.WriteLine($"FPS:{fps}");
121-
_frameRateStopwatch.Restart();
122-
this.Dispatcher.Dispatch(() => button1.Text = fps.ToString());
123-
}
124-
#endif
125114
}
126115
}

SharpConstraintLayout.Maui.Native/Widget/ConstraintSet.Core.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,38 @@ public virtual Constraint GetParameters(int mId)
4242
return get(mId);
4343
}
4444

45+
public virtual void Clone(params KeyValuePair<int, Constraint>[] constraints)
46+
{
47+
foreach (var keyValuePair in constraints)
48+
{
49+
if (keyValuePair.Value == null)
50+
{
51+
continue;
52+
}
53+
if (mConstraints.ContainsKey(keyValuePair.Key))
54+
{
55+
mConstraints[keyValuePair.Key] = keyValuePair.Value.Clone();
56+
}
57+
else
58+
{
59+
mConstraints.Add(keyValuePair.Key, keyValuePair.Value.Clone());
60+
}
61+
}
62+
}
63+
64+
public virtual void Clone(ConstraintSet set)
65+
{
66+
mConstraints.Clear();
67+
foreach (var keyValuePair in set.mConstraints)
68+
{
69+
if (keyValuePair.Value == null)
70+
{
71+
continue;
72+
}
73+
mConstraints.Add(keyValuePair.Key, keyValuePair.Value.Clone());
74+
}
75+
}
76+
4577
/// <summary>
4678
/// 该方案是和Android的思路一样,在ConstraintLayout中存储一份不变的Constraints去替代LayoutParams,
4779
/// LayoutParams是不变的,因此模仿Android思路Constraints也是不变的字典,不在字典中创建新的Constraint替换,只是改原有的属性

SharpConstraintLayout.Maui.Native/Widget/FluentConstraintSet.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ private void ApiDesign()
3232
{
3333
using (var c = new FluentConstraintSet())
3434
{
35-
c.Clone(null);
35+
// c.Clone(null);
3636
c.Select(null).LeftToLeft(null).LeftToRight(null)
3737
.Select(null).RightToLeft(null).RightToRight(null)
3838
.Select(null).TopToTop(null).TopToBottom(null)

SharpConstraintLayout.Maui/SharpConstraintLayout.Maui.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
1616
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
1717
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
18-
<Version>2.1.1.7</Version>
18+
<Version>2.1.1.8</Version>
1919
<Description>constraintlayout for maui</Description>
2020
<Copyright></Copyright>
2121
<PackageProjectUrl>https://github.com/xtuzy/SharpConstraintLayout</PackageProjectUrl>

SharpConstraintLayout.Maui/Widget/ConstraintLayoutAnimationExtension.Maui.cs

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
namespace SharpConstraintLayout.Maui.Widget
99
{
10+
/// <summary>
11+
/// If you need more complex animation, you can learn form here.
12+
/// </summary>
1013
public static class ConstraintLayoutAnimationExtension
1114
{
1215
public static void LayoutToWithAnim(this ConstraintLayout layout, ConstraintSet finishSet, string animName, uint rate = 16, uint length = 250, Easing easing = null, Action<double, bool> finished = null, Func<bool> repeat = null)
@@ -20,19 +23,22 @@ public static void LayoutToWithAnim(this ConstraintLayout layout, ConstraintSet
2023

2124
public static Animation CreateAnimation(this ConstraintLayout layout, ConstraintSet finish, Easing easing)
2225
{
23-
var startLayoutTreeInfo = layout.CaptureLayoutTreeInfo();
26+
var startLayoutTreeInfo = layout.CaptureLayoutTreeInfo(true);
2427
finish.ApplyToForAnim(layout);
2528
var finfishLayoutTreeInfo = layout.CaptureLayoutTreeInfo(true);
26-
return GenerateAnimation(layout, startLayoutTreeInfo, finfishLayoutTreeInfo, easing);
29+
var anim = GenerateAnimation(layout, startLayoutTreeInfo, finfishLayoutTreeInfo, easing);
30+
return anim;
2731
}
2832

29-
public static Animation CreateAnimation(this ConstraintLayout layout, ConstraintSet start, ConstraintSet finish)
33+
public static Animation CreateAnimation(this ConstraintLayout layout, ConstraintSet start, ConstraintSet finish, Easing easing)
3034
{
3135
start.ApplyToForAnim(layout);
3236
var startLayoutTreeInfo = layout.CaptureLayoutTreeInfo(true);
3337
finish.ApplyToForAnim(layout);
3438
var finfishLayoutTreeInfo = layout.CaptureLayoutTreeInfo(true);
35-
return GenerateAnimation(layout, startLayoutTreeInfo, finfishLayoutTreeInfo);
39+
var anim = GenerateAnimation(layout, startLayoutTreeInfo, finfishLayoutTreeInfo, easing);
40+
//start.ApplyToForAnim(layout);//restore start state
41+
return anim;
3642
}
3743

3844
static Animation GenerateAnimation(ConstraintLayout layout, Dictionary<int, ViewInfo> startLayoutTreeInfo, Dictionary<int, ViewInfo> finfishLayoutTreeInfo, Easing easing = null)
@@ -43,34 +49,40 @@ static Animation GenerateAnimation(ConstraintLayout layout, Dictionary<int, View
4349
var view = layout.FindElementById(item.Key);
4450
var startInfo = item.Value;
4551
var finishInfo = finfishLayoutTreeInfo[item.Key];
52+
if (startInfo.Equals(finishInfo)) continue;
53+
var diffInfo = startInfo.Diff(finishInfo);
4654
animation.Add(0, 1, new Animation((v) =>
4755
{
48-
var rect = new Rect((startInfo.X + (finishInfo.X - startInfo.X) * v),
49-
(startInfo.Y + (finishInfo.Y - startInfo.Y) * v),
50-
(startInfo.Size.Width + (finishInfo.Size.Width - startInfo.Size.Width) * v),
51-
(startInfo.Size.Height + (finishInfo.Size.Height - startInfo.Size.Height) * v));
52-
layout.LayoutChild(view, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
53-
//view.Layout(rect);
54-
view.TranslationX = (finishInfo.TranlateX - startInfo.TranlateX) * v;
55-
view.TranslationY = (finishInfo.TranlateY - startInfo.TranlateY) * v;
56-
/*Func<double, Rect> computeBounds = progress =>
56+
if (diffInfo.X != 0 || diffInfo.Y != 0 || diffInfo.Size.Width != 0 || diffInfo.Size.Height != 0)
5757
{
58-
double x = startInfo.X + (finishInfo.X - startInfo.X) * progress;
59-
double y = startInfo.Y + (finishInfo.Y - startInfo.Y) * progress;
60-
double w = startInfo.Size.Width + (finishInfo.Size.Width - finishInfo.Size.Width) * progress;
61-
double h = startInfo.Size.Height + (finishInfo.Size.Height - finishInfo.Size.Height) * progress;
58+
var rect = new Rect((startInfo.X + diffInfo.X * v),
59+
(startInfo.Y + diffInfo.Y * v),
60+
(startInfo.Size.Width + diffInfo.Size.Width * v),
61+
(startInfo.Size.Height + diffInfo.Size.Height * v));
62+
layout.LayoutChild(view, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
63+
}
6264

63-
return new Rect(x, y, w, h);
64-
};
65-
view.Layout(computeBounds(v));*/
66-
view.Rotation = startInfo.Rotation + (finishInfo.Rotation - startInfo.Rotation) * v;
67-
view.RotationX = startInfo.RotationX + (finishInfo.RotationX - startInfo.RotationX) * v;
68-
view.RotationY = startInfo.RotationY + (finishInfo.RotationY - startInfo.RotationY) * v;
65+
if (diffInfo.TranlateX != 0)
66+
view.TranslationX = diffInfo.TranlateX * v;
67+
if (diffInfo.TranlateY != 0)
68+
view.TranslationY = diffInfo.TranlateY * v;
69+
if (diffInfo.Rotation != 0)
70+
view.Rotation = startInfo.Rotation + diffInfo.Rotation * v;
71+
if (diffInfo.RotationX != 0)
72+
view.RotationX = startInfo.RotationX + diffInfo.RotationX * v;
73+
if (diffInfo.RotationY != 0)
74+
view.RotationY = startInfo.RotationY + diffInfo.RotationY * v;
6975
//view.RotationZ = (finishInfo.RotationZ - startInfo.RotationZ) * v;
70-
view.Scale = startInfo.Scale + (finishInfo.Scale - startInfo.Scale) * v;
71-
view.ScaleX = startInfo.ScaleX + (finishInfo.ScaleX - startInfo.ScaleX) * v;
72-
view.ScaleY = startInfo.ScaleY + (finishInfo.ScaleY - startInfo.ScaleY) * v;
73-
view.Opacity = startInfo.Alpha + (finishInfo.Alpha - startInfo.Alpha) * v;
76+
77+
if (diffInfo.Scale != 0)
78+
view.Scale = startInfo.Scale + diffInfo.Scale * v;
79+
if (diffInfo.ScaleX != 0)
80+
view.ScaleX = startInfo.ScaleX + diffInfo.ScaleX * v;
81+
if (diffInfo.ScaleY != 0)
82+
view.ScaleY = startInfo.ScaleY + diffInfo.ScaleY * v;
83+
84+
if (diffInfo.Alpha != 0)
85+
view.Opacity = startInfo.Alpha + diffInfo.Alpha * v;
7486
}, 0, 1, easing));
7587
}
7688
return animation;

SharpConstraintLayout.Maui/Widget/ViewInfo.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,64 @@ public class ViewInfo
2020
public double Rotation;
2121
public double RotationX;
2222
public double RotationY;
23+
24+
public override bool Equals(object? obj)
25+
{
26+
var finish = obj as ViewInfo;
27+
if (finish == null)
28+
return false;
29+
if (Math.Round(X, 3) != Math.Round(finish.X))
30+
return false;
31+
if (Math.Round(Y) != Math.Round(finish.Y))
32+
return false;
33+
if (Math.Round(Size.Width) != Math.Round(finish.Size.Width))
34+
return false;
35+
if (Math.Round(Size.Height) != Math.Round(finish.Size.Height))
36+
return false;
37+
if (Math.Round(TranlateX) != Math.Round(finish.TranlateX))
38+
return false;
39+
if (Math.Round(TranlateY) != Math.Round(finish.TranlateY))
40+
return false;
41+
if (Math.Round(Scale) != Math.Round(finish.Scale))
42+
return false;
43+
if (Math.Round(ScaleX) != Math.Round(finish.ScaleX))
44+
return false;
45+
if (Math.Round(ScaleY) != Math.Round(finish.ScaleY))
46+
return false;
47+
if (Math.Round(Alpha) != Math.Round(finish.Alpha))
48+
return false;
49+
if (Math.Round(Rotation) != Math.Round(finish.Rotation))
50+
return false;
51+
if (Math.Round(RotationX) != Math.Round(finish.RotationX))
52+
return false;
53+
if (Math.Round(RotationY) != Math.Round(finish.RotationY))
54+
return false;
55+
56+
return true;
57+
}
58+
59+
/// <summary>
60+
/// 求差值
61+
/// </summary>
62+
/// <param name="finish"></param>
63+
/// <returns></returns>
64+
public ViewInfo Diff(ViewInfo finish)
65+
{
66+
return new ViewInfo()
67+
{
68+
X = finish.X - X,
69+
Y = finish.Y - Y,
70+
Size = new Size(finish.Size.Width - Size.Width, finish.Size.Height - Size.Height),
71+
TranlateX = finish.TranlateX - TranlateX,
72+
TranlateY = finish.TranlateY - TranlateY,
73+
Scale = finish.Scale - Scale,
74+
ScaleX = finish.ScaleX - ScaleX,
75+
ScaleY = finish.ScaleY - ScaleY,
76+
Alpha = finish.Alpha - Alpha,
77+
Rotation = finish.Rotation - Rotation,
78+
RotationX = finish.RotationX - RotationX,
79+
RotationY = finish.RotationY - RotationY
80+
};
81+
}
2382
}
2483
}

0 commit comments

Comments
 (0)