zoukankan      html  css  js  c++  java
  • WP7:模拟开始屏幕Tile漂动效果

    在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

  • 相关阅读:
    redis(二)高级用法
    redis(一) 安装以及基本数据类型操作
    RabbitMQ(五) -- topics
    JS实时数据运算
    Access数据库中Sum函数返回空值(Null)时如何设置为0
    asp检测数字类型函数
    MVC:从客户端中检测到有潜在危险的 Request.Form 值 的解决方法
    WIN8系统安装软件时提示"扩展属性不一致"的解决方法
    免费的网络扫描器-Advanced IP Scanner
    中国电信大亚DP607光猫破解,设置路由,wifi!关闭远程管理,改连接限制,SN码查询!
  • 原文地址:https://www.cnblogs.com/CharlesGrant/p/3639243.html
Copyright © 2011-2022 走看看