Skip to content

Commit a6a0057

Browse files
Bug/transitioner blank (#2941)
* Code refactor, research into transition animations * Fixes the fast switching bug
1 parent 8d3770c commit a6a0057

File tree

5 files changed

+129
-66
lines changed

5 files changed

+129
-66
lines changed

MainDemo.Wpf/TransitionsDemo/Slide6_Origins.xaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121
Grid.Column="1"
2222
DefaultTransitionOrigin="1, 1"
2323
SelectedIndex="0">
24-
<Border Background="#009688">
25-
<TextBlock Margin="24"
24+
<materialDesign:TransitionerSlide>
25+
<Border Background="#009688">
26+
<TextBlock Margin="24"
2627
Foreground="Azure"
2728
TextWrapping="Wrap">
2829
You can set .DefaultTransitionOrigin, to help with transitions such as the circle wipe, which are triggered from code.
29-
</TextBlock>
30-
</Border>
30+
</TextBlock>
31+
</Border>
32+
</materialDesign:TransitionerSlide>
3133
<materialDesign:TransitionerSlide TransitionOrigin="0.25, 0.25">
3234
<materialDesign:TransitionerSlide.BackwardWipe>
3335
<materialDesign:CircleWipe />
Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,38 @@
1+
using System.Diagnostics;
12
using System.Windows.Media;
23
using System.Windows.Media.Animation;
34

45
namespace MaterialDesignThemes.Wpf.Transitions
56
{
67
public class CircleWipe : ITransitionWipe
78
{
9+
private KeyTime startKeyTime, midKeyTime, endKeyTime;
10+
11+
public CircleWipe()
12+
{
13+
startKeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero);
14+
midKeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(200));
15+
endKeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(400));
16+
}
17+
818
public void Wipe(TransitionerSlide fromSlide, TransitionerSlide toSlide, Point origin, IZIndexController zIndexController)
919
{
10-
if (fromSlide == null) throw new ArgumentNullException(nameof(fromSlide));
11-
if (toSlide == null) throw new ArgumentNullException(nameof(toSlide));
12-
if (zIndexController == null) throw new ArgumentNullException(nameof(zIndexController));
20+
if (fromSlide == null)
21+
{
22+
throw new ArgumentNullException(nameof(fromSlide));
23+
}
24+
if (toSlide == null)
25+
{
26+
throw new ArgumentNullException(nameof(toSlide));
27+
}
28+
if (zIndexController == null)
29+
{
30+
throw new ArgumentNullException(nameof(zIndexController));
31+
}
1332

14-
var horizontalProportion = Math.Max(1.0 - origin.X, 1.0 * origin.X);
15-
var verticalProportion = Math.Max(1.0 - origin.Y, 1.0 * origin.Y);
16-
var radius = Math.Sqrt(Math.Pow(toSlide.ActualWidth * horizontalProportion, 2) + Math.Pow(toSlide.ActualHeight * verticalProportion, 2));
33+
double horizontalProportion = Math.Max(1.0 - origin.X, 1.0 * origin.X);
34+
double verticalProportion = Math.Max(1.0 - origin.Y, 1.0 * origin.Y);
35+
double radius = Math.Sqrt(Math.Pow(toSlide.ActualWidth * horizontalProportion, 2) + Math.Pow(toSlide.ActualHeight * verticalProportion, 2));
1736

1837
var scaleTransform = new ScaleTransform(0, 0);
1938
var translateTransform = new TranslateTransform(toSlide.ActualWidth * origin.X, toSlide.ActualHeight * origin.Y);
@@ -30,32 +49,42 @@ public void Wipe(TransitionerSlide fromSlide, TransitionerSlide toSlide, Point o
3049
toSlide.SetCurrentValue(UIElement.ClipProperty, ellipseGeometry);
3150
zIndexController.Stack(toSlide, fromSlide);
3251

33-
var zeroKeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero);
34-
var midKeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(200));
35-
var endKeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(400));
52+
var opacityAnimation = SetupOpacityAnimation(fromSlide);
53+
fromSlide.BeginAnimation(UIElement.OpacityProperty, opacityAnimation);
3654

37-
var opacityAnimation = new DoubleAnimationUsingKeyFrames();
38-
opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(1, zeroKeyTime));
39-
opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(1, midKeyTime));
40-
opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, endKeyTime));
55+
var scaleAnimation = SetupScaleAnimation(fromSlide, toSlide);
56+
scaleTransform.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
57+
scaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation);
58+
}
59+
60+
private DoubleAnimationUsingKeyFrames SetupScaleAnimation(TransitionerSlide fromSlide, TransitionerSlide toSlide)
61+
{
62+
var scaleAnimation = new DoubleAnimationUsingKeyFrames();
63+
scaleAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, startKeyTime));
64+
scaleAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(1, endKeyTime));
65+
scaleAnimation.Completed += (sender, args) =>
66+
{
67+
toSlide.SetCurrentValue(UIElement.ClipProperty, null);
68+
fromSlide.BeginAnimation(UIElement.OpacityProperty, null);
69+
};
70+
return scaleAnimation;
71+
}
72+
private DoubleAnimationUsingKeyFrames SetupOpacityAnimation(TransitionerSlide fromSlide)
73+
{
74+
var opacityAnimation = GenerateThreeStepAnimation();
4175
opacityAnimation.Completed += (sender, args) =>
4276
{
4377
fromSlide.BeginAnimation(UIElement.OpacityProperty, null);
44-
fromSlide.Opacity = 0;
4578
};
46-
fromSlide.BeginAnimation(UIElement.OpacityProperty, opacityAnimation);
47-
48-
var scaleAnimation = new DoubleAnimationUsingKeyFrames();
49-
scaleAnimation.Completed += (sender, args) =>
50-
{
51-
toSlide.SetCurrentValue(UIElement.ClipProperty, null);
52-
fromSlide.BeginAnimation(UIElement.OpacityProperty, null);
53-
fromSlide.Opacity = 0;
54-
};
55-
scaleAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, zeroKeyTime));
56-
scaleAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(1, endKeyTime));
57-
scaleTransform.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
58-
scaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation);
79+
return opacityAnimation;
80+
}
81+
private DoubleAnimationUsingKeyFrames GenerateThreeStepAnimation()
82+
{
83+
var animation = new DoubleAnimationUsingKeyFrames();
84+
animation.KeyFrames.Add(new EasingDoubleKeyFrame(1, startKeyTime));
85+
animation.KeyFrames.Add(new EasingDoubleKeyFrame(1, midKeyTime));
86+
animation.KeyFrames.Add(new EasingDoubleKeyFrame(0, endKeyTime));
87+
return animation;
5988
}
6089
}
6190
}

MaterialDesignThemes.Wpf/Transitions/FadeWipe.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace MaterialDesignThemes.Wpf.Transitions
55
public class FadeWipe : ITransitionWipe
66
{
77
private readonly SineEase _sineEase = new SineEase();
8+
private readonly KeyTime zeroKeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero);
89

910
/// <summary>
1011
/// Duration of the animation
@@ -18,7 +19,6 @@ public void Wipe(TransitionerSlide fromSlide, TransitionerSlide toSlide, Point o
1819
if (zIndexController == null) throw new ArgumentNullException(nameof(zIndexController));
1920

2021
// Set up time points
21-
var zeroKeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero);
2222
var endKeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(Duration.TotalSeconds / 2));
2323

2424
// From
@@ -39,13 +39,10 @@ public void Wipe(TransitionerSlide fromSlide, TransitionerSlide toSlide, Point o
3939
toAnimation.Completed += (sender, args) =>
4040
{
4141
toSlide.BeginAnimation(UIElement.OpacityProperty, null);
42-
fromSlide.Opacity = 0;
43-
toSlide.Opacity = 1;
4442
};
4543
fromAnimation.Completed += (sender, args) =>
4644
{
4745
fromSlide.BeginAnimation(UIElement.OpacityProperty, null);
48-
fromSlide.Opacity = 0;
4946
toSlide.BeginAnimation(UIElement.OpacityProperty, toAnimation);
5047
};
5148

MaterialDesignThemes.Wpf/Transitions/SlideOutWipe.cs

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,63 @@ namespace MaterialDesignThemes.Wpf.Transitions
66
public class SlideOutWipe : ITransitionWipe
77
{
88
private readonly SineEase _sineEase = new SineEase();
9+
private KeyTime startKeyTime, midKeyTime, endKeyTime;
910

10-
public void Wipe(TransitionerSlide fromSlide, TransitionerSlide toSlide, Point origin, IZIndexController zIndexController)
11+
public SlideOutWipe()
1112
{
12-
if (fromSlide == null) throw new ArgumentNullException(nameof(fromSlide));
13-
if (toSlide == null) throw new ArgumentNullException(nameof(toSlide));
14-
if (zIndexController == null) throw new ArgumentNullException(nameof(zIndexController));
13+
startKeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero);
14+
midKeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(200));
15+
endKeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(400));
16+
}
1517

16-
var zeroKeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero);
17-
var midishKeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(200));
18-
var endKeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(400));
18+
public void Wipe(TransitionerSlide fromSlide, TransitionerSlide toSlide, Point origin, IZIndexController zIndexController)
19+
{
20+
if (fromSlide == null)
21+
{
22+
throw new ArgumentNullException(nameof(fromSlide));
23+
}
24+
if (toSlide == null)
25+
{
26+
throw new ArgumentNullException(nameof(toSlide));
27+
}
28+
if (zIndexController == null)
29+
{
30+
throw new ArgumentNullException(nameof(zIndexController));
31+
}
1932

20-
//back out old slide setup
33+
// Back out old slide setup
2134
var scaleTransform = new ScaleTransform(1, 1);
2235
fromSlide.RenderTransform = scaleTransform;
36+
37+
// Setup scale animation
2338
var scaleAnimation = new DoubleAnimationUsingKeyFrames();
24-
scaleAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(1, zeroKeyTime));
39+
scaleAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(1, startKeyTime));
2540
scaleAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(.8, endKeyTime));
2641
scaleAnimation.Completed += (sender, args) =>
2742
{
2843
fromSlide.RenderTransform = null;
2944
};
45+
46+
// Setup opacity animation
3047
var opacityAnimation = new DoubleAnimationUsingKeyFrames();
31-
opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(1, zeroKeyTime));
48+
opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(1, startKeyTime));
3249
opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, endKeyTime));
3350
opacityAnimation.Completed += (sender, args) =>
3451
{
3552
fromSlide.BeginAnimation(UIElement.OpacityProperty, null);
36-
fromSlide.Opacity = 0;
3753
};
3854

39-
//slide in new slide setup
55+
// Slide in new slide setup
4056
var translateTransform = new TranslateTransform(0, toSlide.ActualHeight);
4157
toSlide.RenderTransform = translateTransform;
58+
59+
// Setup slide animation
4260
var slideAnimation = new DoubleAnimationUsingKeyFrames();
43-
slideAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(toSlide.ActualHeight, zeroKeyTime));
44-
slideAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(toSlide.ActualHeight, midishKeyTime) { EasingFunction = _sineEase });
61+
slideAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(toSlide.ActualHeight, startKeyTime));
62+
slideAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(toSlide.ActualHeight, midKeyTime) { EasingFunction = _sineEase });
4563
slideAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, endKeyTime) { EasingFunction = _sineEase });
4664

47-
//kick off!
65+
// Start animations
4866
translateTransform.BeginAnimation(TranslateTransform.YProperty, slideAnimation);
4967
scaleTransform.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
5068
scaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation);

MaterialDesignThemes.Wpf/Transitions/Transitioner.cs

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Diagnostics;
2+
13
namespace MaterialDesignThemes.Wpf.Transitions
24
{
35
/// <summary>
@@ -165,13 +167,19 @@ private TransitionerSlide GetSlide(object item)
165167

166168
private void ActivateFrame(int selectedIndex, int unselectedIndex)
167169
{
168-
if (!IsLoaded) return;
170+
if (!IsLoaded)
171+
{
172+
return;
173+
}
169174

170175
TransitionerSlide? oldSlide = null, newSlide = null;
171-
for (var index = 0; index < Items.Count; index++)
176+
for (int index = 0; index < Items.Count; index++)
172177
{
173178
var slide = GetSlide(Items[index]);
174-
if (slide == null) continue;
179+
if (slide == null)
180+
{
181+
continue;
182+
}
175183
if (index == selectedIndex)
176184
{
177185
newSlide = slide;
@@ -189,11 +197,29 @@ private void ActivateFrame(int selectedIndex, int unselectedIndex)
189197
Panel.SetZIndex(slide, 0);
190198
}
191199

192-
if (newSlide != null)
200+
ShowSlide(newSlide);
201+
AnimateTransition(selectedIndex, unselectedIndex, oldSlide, newSlide);
202+
HideSlide(oldSlide);
203+
204+
_nextTransitionOrigin = null;
205+
}
206+
207+
private void HideSlide(TransitionerSlide? slide)
208+
{
209+
if(slide != null)
193210
{
194-
newSlide.Opacity = 1;
211+
slide.Opacity = 0;
195212
}
196-
213+
}
214+
private void ShowSlide(TransitionerSlide? slide)
215+
{
216+
if(slide != null)
217+
{
218+
slide.Opacity = 1;
219+
}
220+
}
221+
private void AnimateTransition(int selectedIndex, int unselectedIndex, TransitionerSlide? oldSlide, TransitionerSlide? newSlide)
222+
{
197223
if (oldSlide != null && newSlide != null)
198224
{
199225
var wipe = selectedIndex > unselectedIndex ? oldSlide.ForwardWipe : oldSlide.BackwardWipe;
@@ -205,21 +231,12 @@ private void ActivateFrame(int selectedIndex, int unselectedIndex)
205231
{
206232
DoStack(newSlide, oldSlide);
207233
}
208-
209-
oldSlide.Opacity = 0;
210234
}
211235
else if (oldSlide != null || newSlide != null)
212236
{
213237
DoStack(oldSlide ?? newSlide);
214-
if (oldSlide != null)
215-
{
216-
oldSlide.Opacity = 0;
217-
}
218238
}
219-
220-
_nextTransitionOrigin = null;
221239
}
222-
223240
private Point GetTransitionOrigin(TransitionerSlide slide)
224241
{
225242
if (_nextTransitionOrigin != null)
@@ -239,7 +256,7 @@ private Point GetTransitionOrigin(TransitionerSlide slide)
239256

240257
private static void DoStack(params TransitionerSlide?[] highestToLowest)
241258
{
242-
var pos = highestToLowest.Length;
259+
int pos = highestToLowest.Length;
243260
foreach (var slide in highestToLowest.Where(s => s != null))
244261
{
245262
Panel.SetZIndex(slide, pos--);

0 commit comments

Comments
 (0)