今天写了一个小动画,把这几天研究的Blend相关知识简单的串接一下,效果那如下面几张图:
也就是在切换横竖屏的时候让按钮产生移动效果,来让他们在切换时移动到正确位置;还有就是横屏左和横屏右时切换,使用旋转加移动。
下面说下整个动画的制作流程
一、首先,创建一个Silverlight for Windows Phone应用程序,让它支持横竖屏,并默认为竖屏
SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
把名为LayoutRoot的Grid控件里的所有子元素删除,并添加如下代码:
<Button x:Name="TopLeftButton" Content="Top Left" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20,20,0,0" Width="200" /> <Button x:Name="TopRightButton" Content="Top Right" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,20,20,0" Width="200" /> <Button x:Name="BottomLeftButton" Content="Bottom Left" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="20,0,0,20" Width="200" /> <Button x:Name="BottomRightButton" Content="Bottom Right" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,20,20" Width="200" />
二、做好这些以后打开Blend(View->Open in Expression Blend)
在Blend的左上角选项卡中点击States,并点击Add state group按钮,添加一个名为OrientationStates的状态分组,并为此分组添加3个状态,分别为Portrait、LandscapeRight和LandscapeLeft。
1、接下来我们选中Portrait点击右边的Add transition的下拉列表选择Portrait->LandscapeRight(这一步是指定状态Portrait到状态LandscapeRight过程时),这时在Portrait节点下面出现LandscapeRight,我们点击LandscapeRight,这时在Objects and timeline会出现时间线,我们在时间线1秒时分别给4个按钮添加一个关键帧,点击 Record Keyframe。再在0秒时为TopLeftButton添加一个关键帧,并把Transform下“+”选项卡里的Y设置为371,同样做法分别设置TopRightButton的X为-489,BottomLeftButton的X为489,BottomRightButton的Y为-371。
重复这一步添加Portrait->LandscapeLeft这一状态转换,设置值为左上按钮0帧时X为489,右上Y为371,左下Y为-371,右下X位-489。
2、在LandscapeRight状态里重复和1类似的步骤添加LandscapeRight->LandscapeLeft,0时给4个按钮设置一个关键帧,但并不做任何操作。在1秒时对TopLeftButton和LandscapeRight设置Transform“+”选项卡里的Y设置为371,同时设置旋转度为720,(在+后面的选项卡里设置)。BottomLeftButton和BottomRightButton的Transform里Y设置为-371,旋转也设置720。
再添加一个LandscapeRight->Portrait,在1秒时给四个按钮添加一个关键帧,但不做任何操作,再在0秒时添加一个关键帧,设置Transform属性(LT,LR,BL,BR)为(X240,Y660,Y-660,X-240)
在添加一个*->LandscapeRight,操作和Portrait->LandscapeRight完全一样,为什么添加这一帧那?因为当我们首次进入这个页面时,状态是停留在Base时,Base和Portrait是一样的显示效果的,只有当我们更换横竖屏时才会进入LandscapeRight或者LandscapeLeft这时不会执行我们的动画,并且再这之后是不会再次回到Base状态,至于为什么,你要问微软的设计者了。
3.这个步骤和2是完全一样的,只不过设置的值会改变,我就不赘述了。
4.我们可以简单的测试下效果,保存回到Visual Studio中,在cs文件写如下面代码
1 protected override void OnOrientationChanged(OrientationChangedEventArgs e) 2 { 3 base.OnOrientationChanged(e); 4 switch (e.Orientation) 5 { 6 case PageOrientation.Portrait: 7 case PageOrientation.PortraitDown: 8 case PageOrientation.PortraitUp: 9 VisualStateManager.GoToState(nCtrl, "Portrait", true); 10 break; 11 case PageOrientation.LandscapeLeft: 12 VisualStateManager.GoToState(nCtrl, "LandscapeLeft", true); 13 break; 14 case PageOrientation.LandscapeRight: 15 VisualStateManager.GoToState(nCtrl, "LandscapeRight", true); 16 break; 17 case PageOrientation.Landscape: 18 break; 19 } 20 }
就可以运行看到效果了,和上面的效果图是一样的,不过到这里并没有结束。我们要做最后的一个事件绑定。
三、先把步骤二下的4添加的代码删掉。新建一个文件OrientationActive.cs。加入下面代码
1 using Microsoft.Phone.Controls; 2 using System.Windows.Interactivity; 3 using System.Windows; 4 5 namespace PhoneApp1 6 { 7 public class OrientationActive : TriggerAction<PhoneApplicationPage> 8 { 9 #region -- 自定义依赖属性 -- 10 public static readonly DependencyProperty LandscapeLeftStateNameProperty = 11 DependencyProperty.Register("LandscapeLeftStateName", typeof(string), typeof(OrientationActive), new PropertyMetadata("LandscapeLeft")); 12 public string LandscapeLeftStateName 13 { 14 get { return (string)GetValue(LandscapeLeftStateNameProperty); } 15 set { SetValue(LandscapeLeftStateNameProperty, value); } 16 } 17 18 public static readonly DependencyProperty LandscapeRightStateNameProperty = 19 DependencyProperty.Register("LandscapeRightStateName", typeof(string), typeof(OrientationActive), new PropertyMetadata("LandscapeRight")); 20 public string LandscapeRightStateName 21 { 22 get { return (string)GetValue(LandscapeRightStateNameProperty); } 23 set { SetValue(LandscapeRightStateNameProperty, value); } 24 } 25 26 public static readonly DependencyProperty PortraitRightStateNameProperty = 27 DependencyProperty.Register("PortraitRightStateName", typeof(string), typeof(OrientationActive), new PropertyMetadata("Portrait")); 28 public string PortraitRightStateName 29 { 30 get { return (string)GetValue(PortraitRightStateNameProperty); } 31 set { SetValue(PortraitRightStateNameProperty, value); } 32 } 33 #endregion 34 35 protected override void Invoke(object parameter) 36 { 37 var nCtrl = this.AssociatedObject; 38 var NewOrientation = (parameter as OrientationChangedEventArgs).Orientation; 39 40 switch (NewOrientation) 41 { 42 case PageOrientation.Portrait: 43 case PageOrientation.PortraitDown: 44 case PageOrientation.PortraitUp: 45 VisualStateManager.GoToState(nCtrl, "Portrait", true); 46 break; 47 case PageOrientation.LandscapeLeft: 48 VisualStateManager.GoToState(nCtrl, "LandscapeLeft", true); 49 break; 50 case PageOrientation.LandscapeRight: 51 VisualStateManager.GoToState(nCtrl, "LandscapeRight", true); 52 break; 53 case PageOrientation.Landscape: 54 break; 55 } 56 } 57 } 58 }
最要是添加了3个自定义依赖属性,并重写了Invoke,目的是为绑定OnOrientationChanged事件做准备。
写好这个文件,我们再次打开blend在Assets中的Behaciours找到我们定义的行为OrientationActive,并把它拖到Objects and timeline下phoneAppcationPage节点上,这时在右边的Properties中把EventName属性选择为OnOrientationChanged,保存,回到Visual Studio。到此算是大功告成了,我们可以运行看看。并回去好好研究下Blend生成的代码,这个是很有意义的。