Skip to content

Commit

Permalink
Merge pull request #16 from xtuzy/Modify
Browse files Browse the repository at this point in the history
main work is optimize animation
  • Loading branch information
xtuzy authored Jun 20, 2022
2 parents 5a1dbad + 56ac375 commit 4a2fb11
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 70 deletions.
71 changes: 30 additions & 41 deletions SharpConstraintLayout.Maui.Example/Pages/ShowAnimationView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ public ShowAnimationView()
private void Button2_Clicked(object sender, EventArgs e)
{
#if WINDOWS|| __ANDROID__||__IOS__
/*if (_frameRateCalculateTimer == null)
FrameRate();*/
if (fr == null)
{
fr = new BlogFrameRate.FrameRateCalculator();
Expand All @@ -58,26 +56,47 @@ private void Button2_Clicked(object sender, EventArgs e)
}
#endif
layout.AbortAnimation("ConstrainTo");
//layout.AbortAnimation("ConstrainTo");
if (isExpaned)//ÐèÒªÊÕËõ
{
var finish = new FluentConstraintSet();
finish.Clone(layout);
finish.Select(backgroundView).Clear().TopToTop().LeftToLeft().Height(50).MinHeight(20).Width(SizeBehavier.MatchParent)
var beginState = new FluentConstraintSet();
beginState.Clone(layout);

var button1FinishState = new FluentConstraintSet();
button1FinishState.Clone(layout);
button1FinishState.Select(button1).Clear().CenterYTo().RightToRight();

var button23FinishState = new FluentConstraintSet();
button23FinishState.Clone(layout);
button23FinishState.Select(backgroundView).Clear().TopToTop().LeftToLeft().Height(50).MinHeight(20).Width(SizeBehavier.MatchParent)
.Select(button2).Clear().BottomToBottom(null, 20).RightToRight(null, 20)
.Select(button3).Clear().CenterYTo(button2).RightToLeft(button2, 50).Rotation(-90).Scale(2).Alpha(0.3f)
;
layout.LayoutToWithAnim(finish, "ConstrainTo", 16, 1200, Easing.SpringOut);

var button1Anim = layout.CreateAnimation(beginState, button1FinishState, Easing.Linear);

var button2Anim = layout.CreateAnimation(beginState, button23FinishState, Easing.Linear);

var allAnim = new Animation()
{
{ 0, 1, button2Anim },
{ 0.5, 1, button1Anim }
};
allAnim.Commit(layout, "ConstrainTo", 16, 3000, Easing.Linear, (v, b) =>
{
//When finish,we need combine all button state
button23FinishState.Clone(new KeyValuePair<int, ConstraintSet.Constraint>(button1.GetId(), button1FinishState.GetConstraint(button1.GetId())));
button23FinishState.ApplyTo(layout);
});
}
else
{
var start = new FluentConstraintSet();
start.Clone(layout);
start.Select(backgroundView).Clear().TopToTop().EdgesXTo().Width(SizeBehavier.MatchConstraint).PercentHeight(0.5f).Height(SizeBehavier.MatchConstraint)
var button23FinishState = new FluentConstraintSet();
button23FinishState.Clone(layout);
button23FinishState.Select(backgroundView).Clear().TopToTop().EdgesXTo().Width(SizeBehavier.MatchConstraint).PercentHeight(0.5f).Height(SizeBehavier.MatchConstraint)
.Select(button2).Clear().BottomToBottom(backgroundView, 20).RightToRight(backgroundView, 20)
.Select(button3).Clear().BottomToTop(button2, 20).CenterXTo(button2).Rotation(0)
;
layout.LayoutToWithAnim(start, "ConstrainTo", 8, 3000, Easing.SpringOut);
layout.LayoutToWithAnim(button23FinishState, "ConstrainTo", 16, 3000, Easing.SpringOut);
}
isExpaned = !isExpaned;
}
Expand All @@ -92,35 +111,5 @@ private void Button1_Clicked(object sender, EventArgs e)
finish.Select(button1).Clear().CenterYTo().RightToRight();
layout.LayoutToWithAnim(finish, "ConstrainTo", 16, 1200, Easing.SpringOut, (v, b) => { start.ApplyTo(layout); });
}
#if WINDOWS
private uint _counter = 0;
private uint _previousCounter = 0;
private readonly Stopwatch _frameRateStopwatch = new Stopwatch();
private readonly Timer _frameRateCalculateTimer;
void FrameRate()
{

var _frameRateCalculateTimer = new Timer(CalculateFrameRate);
_frameRateStopwatch.Start();
_frameRateCalculateTimer.Change(1000, 1000);
Microsoft.UI.Xaml.Media.CompositionTarget.Rendering += CompositionTarget_Rendering;

}

private void CompositionTarget_Rendering(object sender, object e)
{
_counter++;
}

private void CalculateFrameRate(object state)
{
var frameCount = _counter - _previousCounter;
_previousCounter = _counter;
var fps = ((double)frameCount / _frameRateStopwatch.ElapsedMilliseconds) * 1000;
System.Diagnostics.Debug.WriteLine($"FPS:{fps}");
_frameRateStopwatch.Restart();
this.Dispatcher.Dispatch(() => button1.Text = fps.ToString());
}
#endif
}
}
32 changes: 32 additions & 0 deletions SharpConstraintLayout.Maui.Native/Widget/ConstraintSet.Core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,38 @@ public virtual Constraint GetParameters(int mId)
return get(mId);
}

public virtual void Clone(params KeyValuePair<int, Constraint>[] constraints)
{
foreach (var keyValuePair in constraints)
{
if (keyValuePair.Value == null)
{
continue;
}
if (mConstraints.ContainsKey(keyValuePair.Key))
{
mConstraints[keyValuePair.Key] = keyValuePair.Value.Clone();
}
else
{
mConstraints.Add(keyValuePair.Key, keyValuePair.Value.Clone());
}
}
}

public virtual void Clone(ConstraintSet set)
{
mConstraints.Clear();
foreach (var keyValuePair in set.mConstraints)
{
if (keyValuePair.Value == null)
{
continue;
}
mConstraints.Add(keyValuePair.Key, keyValuePair.Value.Clone());
}
}

/// <summary>
/// 该方案是和Android的思路一样,在ConstraintLayout中存储一份不变的Constraints去替代LayoutParams,
/// LayoutParams是不变的,因此模仿Android思路Constraints也是不变的字典,不在字典中创建新的Constraint替换,只是改原有的属性
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ private void ApiDesign()
{
using (var c = new FluentConstraintSet())
{
c.Clone(null);
// c.Clone(null);
c.Select(null).LeftToLeft(null).LeftToRight(null)
.Select(null).RightToLeft(null).RightToRight(null)
.Select(null).TopToTop(null).TopToBottom(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
<Version>2.1.1.7</Version>
<Version>2.1.1.8</Version>
<Description>constraintlayout for maui</Description>
<Copyright></Copyright>
<PackageProjectUrl>https://github.com/xtuzy/SharpConstraintLayout</PackageProjectUrl>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

namespace SharpConstraintLayout.Maui.Widget
{
/// <summary>
/// If you need more complex animation, you can learn form here.
/// </summary>
public static class ConstraintLayoutAnimationExtension
{
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)
Expand All @@ -20,19 +23,22 @@ public static void LayoutToWithAnim(this ConstraintLayout layout, ConstraintSet

public static Animation CreateAnimation(this ConstraintLayout layout, ConstraintSet finish, Easing easing)
{
var startLayoutTreeInfo = layout.CaptureLayoutTreeInfo();
var startLayoutTreeInfo = layout.CaptureLayoutTreeInfo(true);
finish.ApplyToForAnim(layout);
var finfishLayoutTreeInfo = layout.CaptureLayoutTreeInfo(true);
return GenerateAnimation(layout, startLayoutTreeInfo, finfishLayoutTreeInfo, easing);
var anim = GenerateAnimation(layout, startLayoutTreeInfo, finfishLayoutTreeInfo, easing);
return anim;
}

public static Animation CreateAnimation(this ConstraintLayout layout, ConstraintSet start, ConstraintSet finish)
public static Animation CreateAnimation(this ConstraintLayout layout, ConstraintSet start, ConstraintSet finish, Easing easing)
{
start.ApplyToForAnim(layout);
var startLayoutTreeInfo = layout.CaptureLayoutTreeInfo(true);
finish.ApplyToForAnim(layout);
var finfishLayoutTreeInfo = layout.CaptureLayoutTreeInfo(true);
return GenerateAnimation(layout, startLayoutTreeInfo, finfishLayoutTreeInfo);
var anim = GenerateAnimation(layout, startLayoutTreeInfo, finfishLayoutTreeInfo, easing);
//start.ApplyToForAnim(layout);//restore start state
return anim;
}

static Animation GenerateAnimation(ConstraintLayout layout, Dictionary<int, ViewInfo> startLayoutTreeInfo, Dictionary<int, ViewInfo> finfishLayoutTreeInfo, Easing easing = null)
Expand All @@ -43,34 +49,40 @@ static Animation GenerateAnimation(ConstraintLayout layout, Dictionary<int, View
var view = layout.FindElementById(item.Key);
var startInfo = item.Value;
var finishInfo = finfishLayoutTreeInfo[item.Key];
if (startInfo.Equals(finishInfo)) continue;
var diffInfo = startInfo.Diff(finishInfo);
animation.Add(0, 1, new Animation((v) =>
{
var rect = new Rect((startInfo.X + (finishInfo.X - startInfo.X) * v),
(startInfo.Y + (finishInfo.Y - startInfo.Y) * v),
(startInfo.Size.Width + (finishInfo.Size.Width - startInfo.Size.Width) * v),
(startInfo.Size.Height + (finishInfo.Size.Height - startInfo.Size.Height) * v));
layout.LayoutChild(view, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
//view.Layout(rect);
view.TranslationX = (finishInfo.TranlateX - startInfo.TranlateX) * v;
view.TranslationY = (finishInfo.TranlateY - startInfo.TranlateY) * v;
/*Func<double, Rect> computeBounds = progress =>
if (diffInfo.X != 0 || diffInfo.Y != 0 || diffInfo.Size.Width != 0 || diffInfo.Size.Height != 0)
{
double x = startInfo.X + (finishInfo.X - startInfo.X) * progress;
double y = startInfo.Y + (finishInfo.Y - startInfo.Y) * progress;
double w = startInfo.Size.Width + (finishInfo.Size.Width - finishInfo.Size.Width) * progress;
double h = startInfo.Size.Height + (finishInfo.Size.Height - finishInfo.Size.Height) * progress;
var rect = new Rect((startInfo.X + diffInfo.X * v),
(startInfo.Y + diffInfo.Y * v),
(startInfo.Size.Width + diffInfo.Size.Width * v),
(startInfo.Size.Height + diffInfo.Size.Height * v));
layout.LayoutChild(view, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
}

return new Rect(x, y, w, h);
};
view.Layout(computeBounds(v));*/
view.Rotation = startInfo.Rotation + (finishInfo.Rotation - startInfo.Rotation) * v;
view.RotationX = startInfo.RotationX + (finishInfo.RotationX - startInfo.RotationX) * v;
view.RotationY = startInfo.RotationY + (finishInfo.RotationY - startInfo.RotationY) * v;
if (diffInfo.TranlateX != 0)
view.TranslationX = diffInfo.TranlateX * v;
if (diffInfo.TranlateY != 0)
view.TranslationY = diffInfo.TranlateY * v;
if (diffInfo.Rotation != 0)
view.Rotation = startInfo.Rotation + diffInfo.Rotation * v;
if (diffInfo.RotationX != 0)
view.RotationX = startInfo.RotationX + diffInfo.RotationX * v;
if (diffInfo.RotationY != 0)
view.RotationY = startInfo.RotationY + diffInfo.RotationY * v;
//view.RotationZ = (finishInfo.RotationZ - startInfo.RotationZ) * v;
view.Scale = startInfo.Scale + (finishInfo.Scale - startInfo.Scale) * v;
view.ScaleX = startInfo.ScaleX + (finishInfo.ScaleX - startInfo.ScaleX) * v;
view.ScaleY = startInfo.ScaleY + (finishInfo.ScaleY - startInfo.ScaleY) * v;
view.Opacity = startInfo.Alpha + (finishInfo.Alpha - startInfo.Alpha) * v;

if (diffInfo.Scale != 0)
view.Scale = startInfo.Scale + diffInfo.Scale * v;
if (diffInfo.ScaleX != 0)
view.ScaleX = startInfo.ScaleX + diffInfo.ScaleX * v;
if (diffInfo.ScaleY != 0)
view.ScaleY = startInfo.ScaleY + diffInfo.ScaleY * v;

if (diffInfo.Alpha != 0)
view.Opacity = startInfo.Alpha + diffInfo.Alpha * v;
}, 0, 1, easing));
}
return animation;
Expand Down
59 changes: 59 additions & 0 deletions SharpConstraintLayout.Maui/Widget/ViewInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,64 @@ public class ViewInfo
public double Rotation;
public double RotationX;
public double RotationY;

public override bool Equals(object? obj)
{
var finish = obj as ViewInfo;
if (finish == null)
return false;
if (Math.Round(X, 3) != Math.Round(finish.X))
return false;
if (Math.Round(Y) != Math.Round(finish.Y))
return false;
if (Math.Round(Size.Width) != Math.Round(finish.Size.Width))
return false;
if (Math.Round(Size.Height) != Math.Round(finish.Size.Height))
return false;
if (Math.Round(TranlateX) != Math.Round(finish.TranlateX))
return false;
if (Math.Round(TranlateY) != Math.Round(finish.TranlateY))
return false;
if (Math.Round(Scale) != Math.Round(finish.Scale))
return false;
if (Math.Round(ScaleX) != Math.Round(finish.ScaleX))
return false;
if (Math.Round(ScaleY) != Math.Round(finish.ScaleY))
return false;
if (Math.Round(Alpha) != Math.Round(finish.Alpha))
return false;
if (Math.Round(Rotation) != Math.Round(finish.Rotation))
return false;
if (Math.Round(RotationX) != Math.Round(finish.RotationX))
return false;
if (Math.Round(RotationY) != Math.Round(finish.RotationY))
return false;

return true;
}

/// <summary>
/// 求差值
/// </summary>
/// <param name="finish"></param>
/// <returns></returns>
public ViewInfo Diff(ViewInfo finish)
{
return new ViewInfo()
{
X = finish.X - X,
Y = finish.Y - Y,
Size = new Size(finish.Size.Width - Size.Width, finish.Size.Height - Size.Height),
TranlateX = finish.TranlateX - TranlateX,
TranlateY = finish.TranlateY - TranlateY,
Scale = finish.Scale - Scale,
ScaleX = finish.ScaleX - ScaleX,
ScaleY = finish.ScaleY - ScaleY,
Alpha = finish.Alpha - Alpha,
Rotation = finish.Rotation - Rotation,
RotationX = finish.RotationX - RotationX,
RotationY = finish.RotationY - RotationY
};
}
}
}

0 comments on commit 4a2fb11

Please sign in to comment.