实现Pivot控件单个PivotItem的全屏化

来源:互联网 发布:自动扒带软件 编辑:程序博客网 时间:2024/04/28 07:45

在新浪微博WP7版中有一个蛮酷的特效,就是滑动list的时候直接全屏化界面。

一直想实现这个特效,最终还是类似的实现了这个特效。

 

 

对于ApplicationBar还是很好解决的,直接对IsVisible属性设置为false就能实现,而对上面的Header进行进行隐藏就可以了,经过一番实验貌似用Margin设为负数就能够解决。

 

好接下去看代码:

首先是布局文件。

 

 

Xml代码  收藏代码
  1. <controls:Pivot x:Name="FeaturePivot" Title="{Binding Title}" Foreground="{StaticResource PhoneAccentBrush}">  
  2.   
  3.             <controls:PivotItem x:Name="StoryPivotItem">  
  4.                 <controls:PivotItem.Header>  
  5.                     <TextBlock Text="{Binding Storys.Title}" FontSize="64" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,10,0,0" Foreground="{StaticResource PhoneAccentBrush}"></TextBlock>  
  6.                 </controls:PivotItem.Header>  
  7.   
  8.   
  9.                 <lw:StoryList x:Name="HomeTimeLine" DataContext="{Binding Storys}" />  
  10.             </controls:PivotItem>  
  11. </controls:Pivot>  

 

这里的lw:StoryList是一个UserControl,里面是一个List和ListItem的模版文本,这里不用去管它。但后面它困扰了我很久。

好,由于这是扩展的交互方式,我们可以不用严格的把BackCode写在ViewModel里,我们就直接写在xaml.cs里就行了。

 

 

C#代码  收藏代码
  1. void FullScreenAction()  
  2. {  
  3.     if (this.ApplicationBar.IsVisible == false)  
  4.         return;  
  5.     this.FeaturePivot.Margin = new Thickness(0, -158, 0, 0);  
  6.     this.GlobalProgressBar.Margin = new Thickness(0);  
  7.     this.ApplicationBar.IsVisible = false;  
  8.     this.BackKeyPress += OnFullScreenBackKeyPress;  
  9. }  
  10.   
  11. void StopFullScreenAction()  
  12. {  
  13.     if (this.ApplicationBar.IsVisible == true)  
  14.         return;  
  15.     this.GlobalProgressBar.Margin = new Thickness(80, 32, 120, 0);  
  16.     this.ApplicationBar.IsVisible = true;  
  17.     this.FeaturePivot.Margin = new Thickness(0);  
  18.     this.BackKeyPress -= OnFullScreenBackKeyPress;  
  19. }  
  20.   
  21. private void OnFullScreenBackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)  
  22. {  
  23.     StopFullScreenAction();  
  24.     e.Cancel = true;  
  25. }  

 

这是最挫的实现方式,直接this.FeaturePivot.Margin = new Thickness(0, -158, 0, 0);设置Margin为负值,能达到全屏的效果,但直接隐藏header用户体验很不好。并且这个时候还是能够左右滑动

PS:这里需要注意按后退键是能够退出全屏的,并在退出时清空BackKeyPress这个Event,防止阻碍用户正常退出App。

 

事情一件一件来,先解决左右滑动的问题。toolkit中有一个控件叫lockablePivot,在这里它就可以用了。

 

将上面的xml代码中的controls:Pivot替换成toolkit:LockablePivot,其他不用变,在backcode中再放入一些代码:

 

 

C#代码  收藏代码
  1. void FullScreenAction()  
  2.         {  
  3.             if (this.ApplicationBar.IsVisible == false)  
  4.                 return;  
  5.             this.FeaturePivot.Margin = new Thickness(0, -158, 0, 0);  
  6.             this.GlobalProgressBar.Margin = new Thickness(0);  
  7.             this.ApplicationBar.IsVisible = false;  
  8.             this.FeaturePivot.IsLocked = true//added code  
  9.             this.BackKeyPress += OnFullScreenBackKeyPress;  
  10.         }  
  11.   
  12.         void StopFullScreenAction()  
  13.         {  
  14.             if (this.ApplicationBar.IsVisible == true)  
  15.                 return;  
  16.             this.GlobalProgressBar.Margin = new Thickness(80, 32, 120, 0);  
  17.             this.ApplicationBar.IsVisible = true;  
  18.             this.FeaturePivot.Margin = new Thickness(0);  
  19.             this.FeaturePivot.IsLocked = false//added code  
  20.             this.BackKeyPress -= OnFullScreenBackKeyPress;  
  21.         }  
  22.   
  23.         private void OnFullScreenBackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)  
  24.         {  
  25.             StopFullScreenAction();  
  26.             e.Cancel = true;  
  27.         }  

 只是增加this.FeaturePivot.IsLocked的定值操作就能完美的解决全屏时能滑动的现象。

 

 

 接下来,貌似得加点动画才感觉有较好的用户体验,好,继续,我们会对上面的代码继续优化。

 

 到加动画的时候又犯难了,尼玛查文档发现Storyboard根本不支持Margin属性的DoubleAnimation类型的动画,因为Margin在SL中被定义成一个Object,而DoubleAnimation只能对数值类进行补间动画。

不过还是有方案的,就是用RenderTransform下的CompositeTransform的Translate系列属性。

 

直接看代码。

 

 

Xml代码  收藏代码
  1. <phone:PhoneApplicationPage.Resources>  
  2.   
  3.         <Storyboard x:Name="TitleDispear">  
  4.             <DoubleAnimation Duration="0:0:1" To="-158" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"  
  5.             Storyboard.TargetName="FeaturePivot" d:IsOptimized="True">  
  6.                 <DoubleAnimation.EasingFunction>  
  7.                     <CubicEase EasingMode="EaseOut" />  
  8.                 </DoubleAnimation.EasingFunction>  
  9.             </DoubleAnimation>  
  10.               
  11.         </Storyboard>  
  12.           
  13.         <Storyboard x:Name="TitleAppear">  
  14.             <DoubleAnimation Duration="0:0:1" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"  
  15.             Storyboard.TargetName="FeaturePivot" d:IsOptimized="True">  
  16.                 <DoubleAnimation.EasingFunction>  
  17.                     <CubicEase EasingMode="EaseOut" />  
  18.                 </DoubleAnimation.EasingFunction>  
  19.             </DoubleAnimation>  
  20.         </Storyboard>  
  21. </phone:PhoneApplicationPage.Resources>  
  22.   
  23. <!---------------code---------------->  
  24.   
  25. <toolkit:LockablePivot x:Name="FeaturePivot" Title="{Binding Title}" Foreground="{StaticResource PhoneAccentBrush}">  
  26.             <toolkit:LockablePivot.RenderTransform>  
  27.                 <CompositeTransform />  
  28.             </toolkit:LockablePivot.RenderTransform>  
  29.             <i:Interaction.Triggers>  
  30.                 <i:EventTrigger EventName="SelectionChanged">  
  31.                     <cmd:EventToCommand Command="{Binding ChangeSelectionCommand}"  CommandParameter="{Binding ElementName=FeaturePivot}" />  
  32.                 </i:EventTrigger>  
  33.             </i:Interaction.Triggers>  
  34.   
  35.             <controls:PivotItem x:Name="StoryPivotItem">  
  36.                 <controls:PivotItem.RenderTransform>  
  37.                     <CompositeTransform />  
  38.                 </controls:PivotItem.RenderTransform>  
  39.                 <controls:PivotItem.Header>  
  40.                     <TextBlock Text="{Binding Storys.Title}" FontSize="64" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,10,0,0" Foreground="{StaticResource PhoneAccentBrush}"></TextBlock>  
  41.                 </controls:PivotItem.Header>  
  42.   
  43.                 <lw:StoryList x:Name="HomeTimeLine" DataContext="{Binding Storys}" />  
  44.             </controls:PivotItem>  
  45.   
  46. <!------------code--------------->  
  47.   
  48. </toolkit:LockablePivot>  

 在上面的XML文件中定义了两个Storyboard动画资源,全屏化时让FeaturePivot的TranslateY由0->-158,向上溢出,这样就是实现了header的隐藏,所以TranslateY和margin都是可以隐藏header的,但有一点很大的不同,

 

TranslateY不会改变UIElement的大小,而Margin会改变,负数等于是拉伸大小。于是这里问题就产生了,如果光设置TranslateY会导致整个Pivot下方有一部分空白区域。。。所以要着手解决这个问题,也就是这个问题困然了我很久。。。。

 

看backcode代码:

 

C#代码  收藏代码
  1. void FullScreenAction()  
  2. {  
  3.     if (this.ApplicationBar.IsVisible == false)  
  4.         return;  
  5.     this.FeaturePivot.Margin = new Thickness(0, 0, 0, -158);  
  6.     this.GlobalProgressBar.Margin = new Thickness(0);  
  7.     TitleDispear.Begin();  
  8.     this.ApplicationBar.IsVisible = false;  
  9.     this.FeaturePivot.IsLocked = true;  
  10.     this.BackKeyPress += OnFullScreenBackKeyPress;  
  11. }  
  12.   
  13. void StopFullScreenAction()  
  14. {  
  15.     if (this.ApplicationBar.IsVisible == true)  
  16.         return;  
  17.     this.GlobalProgressBar.Margin = new Thickness(80, 32, 120, 0);  
  18.     this.ApplicationBar.IsVisible = true;  
  19.     TitleAppear.Begin();  
  20.     this.FeaturePivot.Margin = new Thickness(0);  
  21.     this.FeaturePivot.IsLocked = false;  
  22.     this.BackKeyPress -= OnFullScreenBackKeyPress;  
  23. //code  
 

 

这里我们再start时先对Pivot的Margin的bottom设置为-158,用户这时候其实是感知不到pivot的大小变化的,因为溢出的看不到,接下来在进行动画的begin操作。就能完美的实现全屏模式了。

 

慢着,如何触发全屏这个动作呢,新浪是这么做的:用户快速下滑List的时候会开启,而上拉时关闭。接下来得加上手势。

 

我们要用到toolkit中的GestureService行为了。

 

前端代码:

 

 

Xml代码  收藏代码
  1. <controls:PivotItem x:Name="StoryPivotItem">  
  2.       <controls:PivotItem.RenderTransform>  
  3.           <CompositeTransform />  
  4.       </controls:PivotItem.RenderTransform>  
  5.       <controls:PivotItem.Header>  
  6.           <TextBlock Text="{Binding Storys.Title}" FontSize="64" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,10,0,0" Foreground="{StaticResource PhoneAccentBrush}"></TextBlock>  
  7.       </controls:PivotItem.Header>  
  8. 下面的语句 -->  
  9.       <toolkit:GestureService.GestureListener>  
  10.           <toolkit:GestureListener Flick="OnStoryGestureListenerFlick"/>  
  11.       </toolkit:GestureService.GestureListener>  
  12. D -->  
  13.       <lw:StoryList x:Name="HomeTimeLine" DataContext="{Binding Storys}" />  
  14.   </controls:PivotItem>  
 

 

BackCode:

 

 

C#代码  收藏代码
  1. private void OnStoryGestureListenerFlick(object sender, FlickGestureEventArgs e)  
  2. {  
  3.     if (SettingsHelper.GetFullScreenMode() == "0")  
  4.         return;  
  5.     if (e.Direction == System.Windows.Controls.Orientation.Horizontal) //判断手势方向  
  6.         return;  
  7.     //if (e.Angle < 260 || e.Angle > 280) //角度判断,可以不用  
  8.     //    return;  
  9.     if (e.VerticalVelocity < 0) //垂直速度判断  
  10.     {  
  11.         FullScreenAction();  
  12.     }  
  13.     else  
  14.     {  
  15.         StopFullScreenAction();  
  16.     }  
  17. }  

 

 在前端中加入上面的语句来声明一个手势bind,在backcode中进行ActionBind,SettingsHelper.GetFullScreenMode()是设置信息,默认是开启的。

 其他的看注释。

 

好,这样就差不多实现了新浪微博类似的全屏模式。。。出个效果图(顺便宣传一下来往~~,哇咔咔)

 

普通界面:

 

 


 换肤加全屏界面:

 

 转自:http://leyteris.iteye.com/blog/1569418

0 0