In my last post I showed you how to mimic the settings pane used in the Facebook app on windows phone through use of Visual States ( read it here… ).
But that solution was not 100% the same as in the Facebook app, it missed drag gestures.
So, let’s add those 🙂
First you’ll need to add the Windows Phone Toolkit nuget ( http://phone.codeplex.com/ )! Because it has a GestureListener, that you can hook up in XAML to almost any control. It will give you events for all possible windows phone gestures.
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <Grid x:Name=<span style="color: #006080">"Container"</span> Background=<span style="color: #006080">"Transparent"</span>> |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> <toolkit:GestureService.GestureListener> |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> <toolkit:GestureListener DragDelta=<span style="color: #006080">"GestureListener_OnDragDelta"</span> DragCompleted=<span style="color: #006080">"GestureListener_OnDragCompleted"</span> /> |
1 |
<span id="lnum4" style="color: #606060"> 4:</span> </toolkit:GestureService.GestureListener> |
You’ll notice that with this, we are hooking into the DragDelta and DragCompleted events. We are going to use these events to animate our page.
In the OnDragDelta event we will check to see if there has been a Horizontal gesture detected and if so, depending on what pane is already open, show the animation on screen! Take a look at the code below and you’ll notice some tricks to get this done! Basically we calculate how far the user is dragging the content and if he get’s passed DragDistanceToOpen ( or ToClose ), we will start the rest of the animation.
If the user stops the drag gesture before reaching the given distance variable, we animate the screen to the given distance… ( through use of the SetHorizontalOffset method )
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> GestureListener_OnDragDelta(<span style="color: #0000ff">object</span> sender, DragDeltaGestureEventArgs e) |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> { |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> <span style="color: #0000ff">if</span> (e.Direction == System.Windows.Controls.Orientation.Horizontal && e.HorizontalChange > 0 && !_isSettingsOpen) |
1 |
<span id="lnum4" style="color: #606060"> 4:</span> { |
1 |
<span id="lnum5" style="color: #606060"> 5:</span> <span style="color: #0000ff">double</span> offset = _feRoot.GetHorizontalOffset().Value + e.HorizontalChange; |
1 |
<span id="lnum6" style="color: #606060"> 6:</span> <span style="color: #0000ff">if</span> (offset > _dragDistanceToOpen) |
1 |
<span id="lnum7" style="color: #606060"> 7:</span> <span style="color: #0000ff">this</span>.OpenSettings(); |
1 |
<span id="lnum8" style="color: #606060"> 8:</span> <span style="color: #0000ff">else</span> |
1 |
<span id="lnum9" style="color: #606060"> 9:</span> { |
1 |
<span id="lnum10" style="color: #606060"> 10:</span> _feRoot.SetHorizontalOffset(offset); |
1 |
<span id="lnum11" style="color: #606060"> 11:</span> _feSettings.SetHorizontalOffset(offset); |
1 |
<span id="lnum12" style="color: #606060"> 12:</span> } |
1 |
<span id="lnum13" style="color: #606060"> 13:</span> } |
1 |
<span id="lnum14" style="color: #606060"> 14:</span>  |
1 |
<span id="lnum15" style="color: #606060"> 15:</span> <span style="color: #0000ff">if</span> (e.Direction == System.Windows.Controls.Orientation.Horizontal && e.HorizontalChange < 0 && _isSettingsOpen) |
1 |
<span id="lnum16" style="color: #606060"> 16:</span> { |
1 |
<span id="lnum17" style="color: #606060"> 17:</span> <span style="color: #0000ff">double</span> offsetRoot = _feRoot.GetHorizontalOffset().Value + e.HorizontalChange; |
1 |
<span id="lnum18" style="color: #606060"> 18:</span> <span style="color: #0000ff">double</span> offsetSettings = _feSettings.GetHorizontalOffset().Value + e.HorizontalChange; |
1 |
<span id="lnum19" style="color: #606060"> 19:</span> <span style="color: #0000ff">if</span> (offsetRoot < _dragDistanceToClose) |
1 |
<span id="lnum20" style="color: #606060"> 20:</span> <span style="color: #0000ff">this</span>.CloseSettings(); |
1 |
<span id="lnum21" style="color: #606060"> 21:</span> <span style="color: #0000ff">else</span> |
1 |
<span id="lnum22" style="color: #606060"> 22:</span> { |
1 |
<span id="lnum23" style="color: #606060"> 23:</span> _feRoot.SetHorizontalOffset(offsetRoot); |
1 |
<span id="lnum24" style="color: #606060"> 24:</span> _feSettings.SetHorizontalOffset(offsetSettings); |
1 |
<span id="lnum25" style="color: #606060"> 25:</span> } |
1 |
<span id="lnum26" style="color: #606060"> 26:</span> } |
1 |
<span id="lnum27" style="color: #606060"> 27:</span> } |
All this does is just animating the screen ‘while’ dragging.
Now next, we use the OnDragCompleted to finalize our animation, it’s almost the same code as above. The only difference now is that if the user has stopped his gesture and he has not passed the given distance, we will now reset the content to it’s original position. Giving us a ‘snap back’ animation.
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> GestureListener_OnDragCompleted(<span style="color: #0000ff">object</span> sender, DragCompletedGestureEventArgs e) |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> { |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> <span style="color: #0000ff">if</span> (e.Direction == System.Windows.Controls.Orientation.Horizontal && e.HorizontalChange > 0 && !_isSettingsOpen) |
1 |
<span id="lnum4" style="color: #606060"> 4:</span> { |
1 |
<span id="lnum5" style="color: #606060"> 5:</span> <span style="color: #0000ff">if</span> (e.HorizontalChange < _dragDistanceToOpen) |
1 |
<span id="lnum6" style="color: #606060"> 6:</span> <span style="color: #0000ff">this</span>.ResetLayoutRoot(); |
1 |
<span id="lnum7" style="color: #606060"> 7:</span> <span style="color: #0000ff">else</span> |
1 |
<span id="lnum8" style="color: #606060"> 8:</span> <span style="color: #0000ff">this</span>.OpenSettings(); |
1 |
<span id="lnum9" style="color: #606060"> 9:</span> } |
1 |
<span id="lnum10" style="color: #606060"> 10:</span>  |
1 |
<span id="lnum11" style="color: #606060"> 11:</span> <span style="color: #0000ff">if</span> (e.Direction == System.Windows.Controls.Orientation.Horizontal && e.HorizontalChange < 0 && _isSettingsOpen) |
1 |
<span id="lnum12" style="color: #606060"> 12:</span> { |
1 |
<span id="lnum13" style="color: #606060"> 13:</span> <span style="color: #0000ff">if</span> (e.HorizontalChange > _dragDistanceNegative) |
1 |
<span id="lnum14" style="color: #606060"> 14:</span> <span style="color: #0000ff">this</span>.ResetLayoutRoot(); |
1 |
<span id="lnum15" style="color: #606060"> 15:</span> <span style="color: #0000ff">else</span> |
1 |
<span id="lnum16" style="color: #606060"> 16:</span> <span style="color: #0000ff">this</span>.CloseSettings(); |
1 |
<span id="lnum17" style="color: #606060"> 17:</span> } |
1 |
<span id="lnum18" style="color: #606060"> 18:</span> } |
To do the actual animation of the pages, we use the Animate method on the given grids ( RootGrid and SettingGrid ), here the OpenSettings example…
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> OpenSettings() |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> { |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> var trans = _feRoot.GetHorizontalOffset().Transform; |
1 |
<span id="lnum4" style="color: #606060"> 4:</span> trans.Animate(trans.X, 380, TranslateTransform.XProperty, 300, 0, <span style="color: #0000ff">new</span> CubicEase |
1 |
<span id="lnum5" style="color: #606060"> 5:</span> { |
1 |
<span id="lnum6" style="color: #606060"> 6:</span> EasingMode = EasingMode.EaseOut |
1 |
<span id="lnum7" style="color: #606060"> 7:</span> }); |
1 |
<span id="lnum8" style="color: #606060"> 8:</span>  |
1 |
<span id="lnum9" style="color: #606060"> 9:</span> trans = _feSettings.GetHorizontalOffset().Transform; |
1 |
<span id="lnum10" style="color: #606060"> 10:</span> trans.Animate(trans.X, 480, TranslateTransform.XProperty, 300, 0, <span style="color: #0000ff">new</span> CubicEase |
1 |
<span id="lnum11" style="color: #606060"> 11:</span> { |
1 |
<span id="lnum12" style="color: #606060"> 12:</span> EasingMode = EasingMode.EaseOut |
1 |
<span id="lnum13" style="color: #606060"> 13:</span> }); |
1 |
<span id="lnum14" style="color: #606060"> 14:</span>  |
1 |
<span id="lnum15" style="color: #606060"> 15:</span> _isSettingsOpen = <span style="color: #0000ff">true</span>; |
1 |
<span id="lnum16" style="color: #606060"> 16:</span> } |
Now… if you’ll try this in your code you will see that some methods are missing! This because we are using some extension methods. I’m not taking credit for this, they are created by Colin Eberhardt, you can follow him on twitter https://twitter.com/ColinEberhardt or take a look at his blog http://www.scottlogic.com/blog/ceberhardt/ !
The extension methods used are: SetHorizontalOffset, GetHorizontalOffset and Animate the actual code is in the example provided below.
So with all this in place you will get a nice settings pane example with drag gestures enabled, just like the facebook app… if they do it the same way? I doubt it 😉
Result
Everything is up on my github, just take a look here https://github.com/Depechie/SettingsPageAnimation
Cheers