WP7:模拟开始屏幕Tile漂动效果
2014-04-01 21:30
447 查看
在WP7手机的开始屏幕,如果你Hold住某一个瓷贴,就会发现除了你按住的那个瓷贴其他全部下沉半透明,然后开始在不停地漂来漂去~~
今天来模仿一下这个效果。
新建一个项目,然后在Grid里放一个ListBox。
OK 开始编写 ListBox 的模版。
首先是ItemsPanelTemplate。
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
我们放一个WrapPanel,让它进行自动排列和换行。
然后就是主要的 ItemTemplate。
<ListBox.ItemTemplate>
<DataTemplate>
<Canvas Width="185" Height="185">
<Grid x:Name="grid">
<Grid.RenderTransform>
<TranslateTransform/>
</Grid.RenderTransform>
<Grid.Resources>
<Storyboard x:Name="sbTranslate">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="grid"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<EasingDoubleKeyFrame x:Name="translateX" KeyTime="00:00:1" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="grid"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<EasingDoubleKeyFrame x:Name="translateY" KeyTime="00:00:1" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<Image Visibility="Collapsed" Source="/Images/StartPage_DeleteFav.png" Width="42" Height="42" HorizontalAlignment="Right" VerticalAlignment="Top" Canvas.ZIndex="1" MouseLeftButtonUp="Image_MouseLeftButtonUp" Margin="-10"/>
<toolkit:HubTile GroupTag="QuickLink" Notification="{Binding Notification}" Message="{Binding Message}" Title="{Binding Title}" Source="{Binding Src}" Background="{StaticResource PhoneAccentBrush}"/>
</Grid>
</Canvas>
</DataTemplate>
</ListBox.ItemTemplate>
这里 放了一个 Grid ,里面很简单,一个 Image 用来 做 右上角删除图标。然后是一个 HubTile,简单模仿一下。
主要的是 Grid 里 写的 资源,两个 DoubleAnimationUsingKeyFrames,用来操作 TranslateTransform。
好,前台很简单。来看看后台。先为 ListBox 添加几个事件:
Loaded="listBox_Loaded" LostFocus="listBox_LostFocus" SelectionChanged="listBox_SelectionChanged"
先来写Loaded 事件:
for (int i = 0; i < listBox.Items.Count; i++)
{
ListBoxItem item = (ListBoxItem)listBox.ItemContainerGenerator.ContainerFromIndex(i);
item.Hold += item_Hold;
}
为每个listboxitem 添加 必须的 Hold 事件。
void item_Hold(object sender, System.Windows.Input.GestureEventArgs e)
{
if (!isHold)
{
isHold = true;
var item = sender as ListBoxItem;
holdItem = item;
for (int i = 0; i < items.Count; i++)
{
ListBoxItem _item = (ListBoxItem)listBox.ItemContainerGenerator.ContainerFromItem(items[i]);
if (_item != item)
{
Transform(1, 0.75, _item, 0.2);
var grid = FindVisualChild<Grid>(_item);
var sb = grid.Resources["sbTranslate"] as Storyboard;
storyList.Add(Bouncing(sb,false), grid.DataContext);
}
else
{
//显示按住item的关闭按钮
var img = FindVisualChild<Image>(_item);
img.Visibility = System.Windows.Visibility.Visible;
}
}
}
}
在item_Hold事件里做了两件事:显示按住item的关闭按钮,其他item 下沉半透明,然后是启动漂动:Bouncing(sb,false);
Bouncing 这个方法,返回一个 DispatcherTimer 第一个参数是一个Storyboard,那这里放入的就是在前台为 Grid 添加的 资源里的 Storyboard。
先是找到这个 ListboxItem 里的 FindVisualChild<Grid>(_item),然后再找出他的 Storyboard。
那重点来说一下这个函数。
private DispatcherTimer Bouncing(Storyboard sb,bool isover)
{
Random random = new Random();
DoubleKeyFrame sp0 = ((DoubleAnimationUsingKeyFrames)sb.Children[0]).KeyFrames[0];
DoubleKeyFrame ea0 = ((DoubleAnimationUsingKeyFrames)sb.Children[0]).KeyFrames[1];
DoubleKeyFrame sp1 = ((DoubleAnimationUsingKeyFrames)sb.Children[1]).KeyFrames[0];
DoubleKeyFrame ea1 = ((DoubleAnimationUsingKeyFrames)sb.Children[1]).KeyFrames[1];
sp0.Value = 0;
sp1.Value = 0;
ea0.Value = 0;
ea1.Value = 0;
DispatcherTimer dispatcherTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(0) };
dispatcherTimer.Tick += delegate
{
sb.Stop();
sp0.Value = ea0.Value;
sp1.Value = ea1.Value;
if (!isover)
{
ea0.Value = random.Next(-10, 10);//随机数 X
ea1.Value = random.Next(-10, 10);//随机数 Y
sb.Begin();
}
dispatcherTimer.Interval = TimeSpan.FromSeconds(random.Next(9, 13) *0.1);
};
if (isover)
sb.Begin();
else
dispatcherTimer.Start();
return dispatcherTimer;
}
先是根据传入的 Storyboard 找出 它里面DoubleAnimationUsingKeyFrames的每个DoubleKeyFrame。
然后在找出每个DoubleKeyFrame的Value,并初始化。
接下来是生成一个DispatcherTimer对象,这里初始化的Interval是0,也就是立马执行下面Tick的事件,不会造成刚开始动画延迟的感觉。
在对ea0和ea1赋值,用一个随机数,范围在-10到10。也这就在这个方圆内漂动。
而上面的sp0和sp1的赋值是为了下一次动画,不是从零开始的。
下面还有一句:dispatcherTimer.Interval = TimeSpan.FromSeconds(random.Next(9, 13) *0.1);
这句是为了让每个Timer的间隔有所不同,就不会造成所有瓷贴同时漂动同时结束的统一动作。
OK,主要的代码都介绍完了,上图
还有很多功能,比如 listBox_SelectionChanged,OnBackKeyPress,StopBouncing,就不多介绍了,这里就说一下我实现的方法思路,
就是通过,调用动画通过 Timer 来控制,来实现 飘动效果。
如果有兴趣,可以继续了解我下面的 DEMO。
BouncingDemo:http://dl.dbank.com/c0upp01pv7
今天来模仿一下这个效果。
新建一个项目,然后在Grid里放一个ListBox。
OK 开始编写 ListBox 的模版。
首先是ItemsPanelTemplate。
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
我们放一个WrapPanel,让它进行自动排列和换行。
然后就是主要的 ItemTemplate。
<ListBox.ItemTemplate>
<DataTemplate>
<Canvas Width="185" Height="185">
<Grid x:Name="grid">
<Grid.RenderTransform>
<TranslateTransform/>
</Grid.RenderTransform>
<Grid.Resources>
<Storyboard x:Name="sbTranslate">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="grid"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<EasingDoubleKeyFrame x:Name="translateX" KeyTime="00:00:1" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="grid"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<EasingDoubleKeyFrame x:Name="translateY" KeyTime="00:00:1" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<Image Visibility="Collapsed" Source="/Images/StartPage_DeleteFav.png" Width="42" Height="42" HorizontalAlignment="Right" VerticalAlignment="Top" Canvas.ZIndex="1" MouseLeftButtonUp="Image_MouseLeftButtonUp" Margin="-10"/>
<toolkit:HubTile GroupTag="QuickLink" Notification="{Binding Notification}" Message="{Binding Message}" Title="{Binding Title}" Source="{Binding Src}" Background="{StaticResource PhoneAccentBrush}"/>
</Grid>
</Canvas>
</DataTemplate>
</ListBox.ItemTemplate>
这里 放了一个 Grid ,里面很简单,一个 Image 用来 做 右上角删除图标。然后是一个 HubTile,简单模仿一下。
主要的是 Grid 里 写的 资源,两个 DoubleAnimationUsingKeyFrames,用来操作 TranslateTransform。
好,前台很简单。来看看后台。先为 ListBox 添加几个事件:
Loaded="listBox_Loaded" LostFocus="listBox_LostFocus" SelectionChanged="listBox_SelectionChanged"
先来写Loaded 事件:
for (int i = 0; i < listBox.Items.Count; i++)
{
ListBoxItem item = (ListBoxItem)listBox.ItemContainerGenerator.ContainerFromIndex(i);
item.Hold += item_Hold;
}
为每个listboxitem 添加 必须的 Hold 事件。
void item_Hold(object sender, System.Windows.Input.GestureEventArgs e)
{
if (!isHold)
{
isHold = true;
var item = sender as ListBoxItem;
holdItem = item;
for (int i = 0; i < items.Count; i++)
{
ListBoxItem _item = (ListBoxItem)listBox.ItemContainerGenerator.ContainerFromItem(items[i]);
if (_item != item)
{
Transform(1, 0.75, _item, 0.2);
var grid = FindVisualChild<Grid>(_item);
var sb = grid.Resources["sbTranslate"] as Storyboard;
storyList.Add(Bouncing(sb,false), grid.DataContext);
}
else
{
//显示按住item的关闭按钮
var img = FindVisualChild<Image>(_item);
img.Visibility = System.Windows.Visibility.Visible;
}
}
}
}
在item_Hold事件里做了两件事:显示按住item的关闭按钮,其他item 下沉半透明,然后是启动漂动:Bouncing(sb,false);
Bouncing 这个方法,返回一个 DispatcherTimer 第一个参数是一个Storyboard,那这里放入的就是在前台为 Grid 添加的 资源里的 Storyboard。
先是找到这个 ListboxItem 里的 FindVisualChild<Grid>(_item),然后再找出他的 Storyboard。
那重点来说一下这个函数。
private DispatcherTimer Bouncing(Storyboard sb,bool isover)
{
Random random = new Random();
DoubleKeyFrame sp0 = ((DoubleAnimationUsingKeyFrames)sb.Children[0]).KeyFrames[0];
DoubleKeyFrame ea0 = ((DoubleAnimationUsingKeyFrames)sb.Children[0]).KeyFrames[1];
DoubleKeyFrame sp1 = ((DoubleAnimationUsingKeyFrames)sb.Children[1]).KeyFrames[0];
DoubleKeyFrame ea1 = ((DoubleAnimationUsingKeyFrames)sb.Children[1]).KeyFrames[1];
sp0.Value = 0;
sp1.Value = 0;
ea0.Value = 0;
ea1.Value = 0;
DispatcherTimer dispatcherTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(0) };
dispatcherTimer.Tick += delegate
{
sb.Stop();
sp0.Value = ea0.Value;
sp1.Value = ea1.Value;
if (!isover)
{
ea0.Value = random.Next(-10, 10);//随机数 X
ea1.Value = random.Next(-10, 10);//随机数 Y
sb.Begin();
}
dispatcherTimer.Interval = TimeSpan.FromSeconds(random.Next(9, 13) *0.1);
};
if (isover)
sb.Begin();
else
dispatcherTimer.Start();
return dispatcherTimer;
}
先是根据传入的 Storyboard 找出 它里面DoubleAnimationUsingKeyFrames的每个DoubleKeyFrame。
然后在找出每个DoubleKeyFrame的Value,并初始化。
接下来是生成一个DispatcherTimer对象,这里初始化的Interval是0,也就是立马执行下面Tick的事件,不会造成刚开始动画延迟的感觉。
在对ea0和ea1赋值,用一个随机数,范围在-10到10。也这就在这个方圆内漂动。
而上面的sp0和sp1的赋值是为了下一次动画,不是从零开始的。
下面还有一句:dispatcherTimer.Interval = TimeSpan.FromSeconds(random.Next(9, 13) *0.1);
这句是为了让每个Timer的间隔有所不同,就不会造成所有瓷贴同时漂动同时结束的统一动作。
OK,主要的代码都介绍完了,上图
还有很多功能,比如 listBox_SelectionChanged,OnBackKeyPress,StopBouncing,就不多介绍了,这里就说一下我实现的方法思路,
就是通过,调用动画通过 Timer 来控制,来实现 飘动效果。
如果有兴趣,可以继续了解我下面的 DEMO。
BouncingDemo:http://dl.dbank.com/c0upp01pv7
相关文章推荐
- [Windows Phone] 如何通过代码实现Start Screen开始屏幕Tiles漂动效果和Layout变换效果?
- Windows Store apps开发[52]Button控件的自定义——模仿开始屏幕中磁贴的按下、移动效果
- <Run>1、什么是快速恢复应用:当你点击 tile 启动了 app 后,再回到开始屏幕
- WP7固定到开始屏幕
- 模拟屏幕震动效果,使用cocos2d-x 3.x
- 模拟屏幕震动效果,使用cocos2d-x 3.x
- 1、android 模拟小球来回撞墙效果(游戏的开始)
- 【2013-09-10 09:52 星期二 Android动画------ 模拟电视机关闭屏幕效果】
- 把记事本文件固定在Win8的开始屏幕
- ANDROID模拟火花粒子的滑动喷射效果
- 移动web模拟客户端实现多方框输入密码效果
- 【POJ 3279 Fliptile】开关问题,模拟
- 通过UIView来模拟 实现 Button的点击效果
- 在android上模拟ios阴影效果
- unity3d学习笔记(十四)--NGUI用Sprite动画和屏幕自适应制作游戏开始场景
- 鼠标拖拽窗口效果(不允许拖出屏幕的可视区域)
- 微信小程序页面滑动屏幕加载数据效果
- 粒子运动效果的模拟
- Android 碎屏效果 (Crack Screen,击碎屏幕)
- C#实现打造气泡屏幕保护效果