Created
July 25, 2014 18:46
-
-
Save dgkanatsios/5991f60daa1b30f03280 to your computer and use it in GitHub Desktop.
A XAML Behavior for a small tap animation for Windows Phone, allows for an event to run after the Storyboard is completed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TapAction : Behavior<FrameworkElement> | |
{ | |
public string EventAfterStoryboard | |
{ | |
get { return (string)GetValue(EventAfterStoryboardProperty); } | |
set { SetValue(EventAfterStoryboardProperty, value); } | |
} | |
// Using a DependencyProperty as the backing store for EventAfterStoryboard. This enables animation, styling, binding, etc... | |
public static readonly DependencyProperty EventAfterStoryboardProperty = | |
DependencyProperty.Register("EventAfterStoryboard", typeof(string), typeof(TapAction), new PropertyMetadata(null)); | |
public object Tag | |
{ | |
get { return (object)GetValue(TagProperty); } | |
set { SetValue(TagProperty, value); } | |
} | |
// Using a DependencyProperty as the backing store for Tag. This enables animation, styling, binding, etc... | |
public static readonly DependencyProperty TagProperty = | |
DependencyProperty.Register("Tag", typeof(object), typeof(TapAction), new PropertyMetadata(null)); | |
public int AnimationDuration | |
{ | |
get { return (int)GetValue(AnimationDurationProperty); } | |
set { SetValue(AnimationDurationProperty, value); } | |
} | |
// Using a DependencyProperty as the backing store for AnimationDuration. This enables animation, styling, binding, etc... | |
public static readonly DependencyProperty AnimationDurationProperty = | |
DependencyProperty.Register("AnimationDuration", typeof(int), typeof(TapAction), new PropertyMetadata(300)); | |
protected override void OnAttached() | |
{ | |
base.OnAttached(); | |
AssociatedObject.Tap += AssociatedObject_Tap; | |
} | |
Storyboard sb; | |
void AssociatedObject_Tap(object sender, System.Windows.Input.GestureEventArgs e) | |
{ | |
if (sb != null) | |
{ | |
sb.Stop(); | |
sb = null; | |
} | |
sb = CreateTapFeedbackStoryboard(AssociatedObject, true, AnimationDuration); | |
if (EventAfterStoryboard != null) | |
sb.Completed += (se, ev) => | |
{ | |
FrameworkElement dob = AssociatedObject.Parent as FrameworkElement; | |
while (!(dob is PhoneApplicationPage)) | |
{ | |
dob = dob.Parent as FrameworkElement; | |
} | |
if(Tag == null) | |
dob.GetType().GetMethod(EventAfterStoryboard, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).Invoke(dob, null); | |
else | |
dob.GetType().GetMethod(EventAfterStoryboard, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).Invoke(dob, new object[]{Tag}); | |
}; | |
sb.Begin(); | |
} | |
protected override void OnDetaching() | |
{ | |
base.OnDetaching(); | |
if (sb != null) | |
{ | |
sb.Stop(); | |
sb = null; | |
} | |
AssociatedObject.Tap -= AssociatedObject_Tap; | |
} | |
//this animates scale, feel free to change it to whatever you like | |
public static Storyboard CreateTapFeedbackStoryboard(FrameworkElement AssociatedObject, bool ignorePreviousScale=false, int duration=300) | |
{ | |
Storyboard sb = new Storyboard(); | |
double originalScaleX = 1; | |
double originalScaleY = 1; | |
if (AssociatedObject.RenderTransform is MatrixTransform) | |
AssociatedObject.RenderTransform = new CompositeTransform(); | |
else if (AssociatedObject.RenderTransform is CompositeTransform && !ignorePreviousScale) | |
{ | |
originalScaleX = (AssociatedObject.RenderTransform as CompositeTransform).ScaleX; | |
originalScaleY = (AssociatedObject.RenderTransform as CompositeTransform).ScaleY; | |
} | |
AssociatedObject.RenderTransformOrigin = new Point(0.5, 0.5); | |
DoubleAnimationUsingKeyFrames scaleAnimation = new DoubleAnimationUsingKeyFrames(); | |
DoubleKeyFrame keyframe1 = new EasingDoubleKeyFrame(); | |
keyframe1.KeyTime = TimeSpan.FromMilliseconds((int)(duration/2)); | |
keyframe1.Value = originalScaleX + 0.2; | |
DoubleKeyFrame keyframe2 = new EasingDoubleKeyFrame(); | |
keyframe2.KeyTime = TimeSpan.FromMilliseconds(duration); | |
keyframe2.Value = originalScaleX; | |
scaleAnimation.KeyFrames.Add(keyframe1); scaleAnimation.KeyFrames.Add(keyframe2); | |
DoubleAnimationUsingKeyFrames scaleAnimation2 = new DoubleAnimationUsingKeyFrames(); | |
DoubleKeyFrame keyframe11 = new EasingDoubleKeyFrame(); | |
keyframe11.KeyTime = TimeSpan.FromMilliseconds((int)(duration/2)); | |
keyframe11.Value = originalScaleY + 0.2; | |
DoubleKeyFrame keyframe21 = new EasingDoubleKeyFrame(); | |
keyframe21.KeyTime = TimeSpan.FromMilliseconds(duration); | |
keyframe21.Value = originalScaleY; | |
scaleAnimation2.KeyFrames.Add(keyframe11); scaleAnimation2.KeyFrames.Add(keyframe21); | |
Storyboard.SetTarget(scaleAnimation, AssociatedObject); | |
Storyboard.SetTarget(scaleAnimation2, AssociatedObject); | |
Storyboard.SetTargetProperty(scaleAnimation, new PropertyPath("(FrameworkElement.RenderTransform).(CompositeTransform.ScaleX)")); | |
Storyboard.SetTargetProperty(scaleAnimation2, new PropertyPath("(FrameworkElement.RenderTransform).(CompositeTransform.ScaleY)")); | |
sb.Children.Add(scaleAnimation); | |
sb.Children.Add(scaleAnimation2); | |
return sb; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment