Visually Located

XAML and GIS

Tilt animation for Windows Phone Runtime

In a previous post I talked about some of the awesome animations and transitions available in Window Phone 8.1 Runtime apps. These animations and transitions were previously only available with a second SDK like the Windows Phone Toolkit or Telerik’s phone controls. One of the most used animations from both toolkit was the tilt animation. This animation shows a user that what they are touching can be tapped and will probably do something when they do tap. I also previously blogged about how you can enable the tilt animation for “unselectable” items. I am happy to say that the tilt animation is now built into all “tappable” controls without having to do anything!

So you would think that would be the end of the post right? I just said “it just works”. This is true for things like ListView/GridView/Buton, but what about when you want to display a StackPanel with a few items in it and those items should be tiltable? Some work is needed to get this working and there are a few ways to accomplish this.

Wrap content in ListViewItem

Much like my previous post, you can easily enable tilt on “normal” items by simply wrapping the elements with a ListViewItem!

<!-- enable tilt by wrapping with a ListViewItem -->
<ListViewItem>
    <StackPanel Margin="0,0,0,9.5">
        <TextBlock Text="Name" Style="{ThemeResource ControlContextualInfoTextBlockStyle}"/>
        <TextBlock Text="Shawn Kendrot" Style="{ThemeResource BodyTextBlockStyle}"/>
    </StackPanel>
</ListViewItem>

This works because of the default style of the ListViewItem uses the PointerUpThemeAnimation and PointerDownThemeAnimation.

Start Storyboard on PointerPressed/Released

A second option to to listen to the PointerPressed and PointerReleased events of an element and play a Storyboard with the

<!-- enable tilt by listening to pointer events -->
<Grid PointerPressed="OnStoryboardGridPressed" 
      PointerReleased="OnStoryboardGridReleased">
    <Grid.Resources>
        <Storyboard x:Key="TiltDownStory">
            <PointerDownThemeAnimation TargetName="LovesPanel" />
        </Storyboard>
        <Storyboard x:Key="TiltUpStory">
            <PointerUpThemeAnimation TargetName="LovesPanel" />
        </Storyboard>
    </Grid.Resources>
    <StackPanel x:Name="LovesPanel" Margin="0,0,0,9.5">
        <TextBlock Text="Loves" Style="{ThemeResource ControlContextualInfoTextBlockStyle}"/>
        <TextBlock Text="XAML" Style="{ThemeResource BodyTextBlockStyle}"/>
    </StackPanel>
</Grid>
private void OnStoryboardGridPressed(object sender, PointerRoutedEventArgs e)
{
    var panel = ((FrameworkElement)sender);
    var story = (Storyboard)panel.Resources["TiltDownStory"];
    PlayStory(story);
}
 
private void OnStoryboardGridReleased(object sender, PointerRoutedEventArgs e)
{
    var panel = ((FrameworkElement)sender);
    var story = (Storyboard)panel.Resources["TiltUpStory"];
    PlayStory(story);
}
 
private void PlayStory(Storyboard story)
{
    // stop just in case it is already playing
    story.Stop();
    story.Begin();
}

When you tap the element, it will play the story.

Use VisualStates

A final option is to create a new control that will use visual states to play the animations. You will need to create you own control, either a UserControl or a custom control. When the element is pressed or released you will change the visual state of the control. For this example I used a UserControl.

protected override void OnPointerPressed(PointerRoutedEventArgs e)
{
    base.OnPointerPressed(e);
    _isPressed = true;
    ChangeState("PointerDown");
}
 
protected override void OnPointerReleased(PointerRoutedEventArgs e)
{
    base.OnPointerReleased(e);
    _isPressed = false;
    ChangeState("PointerUp");
}
 
private void ChangeState(string state, bool useTransitions = true)
{
    VisualStateManager.GoToState(this, state, useTransitions);
}

Define the states in your XAML

<Grid> 
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="TapStates">
            <VisualState x:Name="Normal" />
            <VisualState x:Name="PointerDown">
                <Storyboard>
                    <PointerDownThemeAnimation TargetName="RootPanel" />
                </Storyboard>
            </VisualState>
            <VisualState x:Name="PointerUp">
                <Storyboard>
                    <PointerUpThemeAnimation TargetName="RootPanel" />
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Grid x:Name="RootPanel">
        <!-- place content here -->
    </Grid>
</Grid>

So when you have content that needs to show the tilt animation, you have three ways to do this. You can download my complete transition/animation sample to see these three examples.

Hope that helps!

blog comments powered by Disqus