欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

WP7:模拟开始屏幕Tile漂动效果

程序员文章站 2022-04-12 08:41:42
在wp7手机的开始屏幕,如果你hold住某一个瓷贴,就会发现除了你按住的那个瓷贴其他全部下沉半透明,然后开始在不停地漂来漂去~~ 今天来模仿一下这个效果。 新建一个项目,然后在grid里放一个lis...

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,主要的代码都介绍完了,上图

 WP7:模拟开始屏幕Tile漂动效果
 
还有很多功能,比如 listbox_selectionchanged,onbackkeypress,stopbouncing,就不多介绍了,这里就说一下我实现的方法思路,
就是通过,调用动画通过 timer 来控制,来实现 飘动效果。
如果有兴趣,可以继续了解我下面的 demo。

bouncingdemo:

 

 

摘自 生 的博客