在新浪微博WP7版中有一個蠻酷的特效,就是滑動list的時候直接全屏化界面。
一直想實現這個特效,最終還是類似的實現了這個特效。
對於ApplicationBar還是很好解決的,直接對IsVisible屬性設置爲false就能實現,而對上面的Header進行進行隱藏就可以了,經過一番實驗貌似用Margin設爲負數就能夠解決。
好接下去看代碼:
首先是佈局文件。
- <controls:Pivot x:Name="FeaturePivot" Title="{Binding Title}" Foreground="{StaticResource PhoneAccentBrush}">
- <controls:PivotItem x:Name="StoryPivotItem">
- <controls:PivotItem.Header>
- <TextBlock Text="{Binding Storys.Title}" FontSize="64" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,10,0,0" Foreground="{StaticResource PhoneAccentBrush}"></TextBlock>
- </controls:PivotItem.Header>
- <lw:StoryList x:Name="HomeTimeLine" DataContext="{Binding Storys}" />
- </controls:PivotItem>
- </controls:Pivot>
這裏的lw:StoryList是一個UserControl,裏面是一個List和ListItem的模版文本,這裏不用去管它。但後面它困擾了我很久。
好,由於這是擴展的交互方式,我們可以不用嚴格的把BackCode寫在ViewModel裏,我們就直接寫在xaml.cs裏就行了。
- void FullScreenAction()
- {
- if (this.ApplicationBar.IsVisible == false)
- return;
- this.FeaturePivot.Margin = new Thickness(0, -158, 0, 0);
- this.GlobalProgressBar.Margin = new Thickness(0);
- this.ApplicationBar.IsVisible = false;
- this.BackKeyPress += OnFullScreenBackKeyPress;
- }
- void StopFullScreenAction()
- {
- if (this.ApplicationBar.IsVisible == true)
- return;
- this.GlobalProgressBar.Margin = new Thickness(80, 32, 120, 0);
- this.ApplicationBar.IsVisible = true;
- this.FeaturePivot.Margin = new Thickness(0);
- this.BackKeyPress -= OnFullScreenBackKeyPress;
- }
- private void OnFullScreenBackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
- {
- StopFullScreenAction();
- e.Cancel = true;
- }
這是最挫的實現方式,直接this.FeaturePivot.Margin = new Thickness(0, -158, 0, 0);設置Margin爲負值,能達到全屏的效果,但直接隱藏header用戶體驗很不好。並且這個時候還是能夠左右滑動
PS:這裏需要注意按後退鍵是能夠退出全屏的,並在退出時清空BackKeyPress這個Event,防止阻礙用戶正常退出App。
事情一件一件來,先解決左右滑動的問題。toolkit中有一個控件叫lockablePivot,在這裏它就可以用了。
將上面的xml代碼中的controls:Pivot替換成toolkit:LockablePivot,其他不用變,在backcode中再放入一些代碼:
- void FullScreenAction()
- {
- if (this.ApplicationBar.IsVisible == false)
- return;
- this.FeaturePivot.Margin = new Thickness(0, -158, 0, 0);
- this.GlobalProgressBar.Margin = new Thickness(0);
- this.ApplicationBar.IsVisible = false;
- this.FeaturePivot.IsLocked = true; //added code
- this.BackKeyPress += OnFullScreenBackKeyPress;
- }
- void StopFullScreenAction()
- {
- if (this.ApplicationBar.IsVisible == true)
- return;
- this.GlobalProgressBar.Margin = new Thickness(80, 32, 120, 0);
- this.ApplicationBar.IsVisible = true;
- this.FeaturePivot.Margin = new Thickness(0);
- this.FeaturePivot.IsLocked = false; //added code
- this.BackKeyPress -= OnFullScreenBackKeyPress;
- }
- private void OnFullScreenBackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
- {
- StopFullScreenAction();
- e.Cancel = true;
- }
只是增加this.FeaturePivot.IsLocked的定值操作就能完美的解決全屏時能滑動的現象。
接下來,貌似得加點動畫才感覺有較好的用戶體驗,好,繼續,我們會對上面的代碼繼續優化。
到加動畫的時候又犯難了,尼瑪查文檔發現Storyboard根本不支持Margin屬性的DoubleAnimation類型的動畫,因爲Margin在SL中被定義成一個Object,而DoubleAnimation只能對數值類進行補間動畫。
不過還是有方案的,就是用RenderTransform下的CompositeTransform的Translate系列屬性。
直接看代碼。
- <phone:PhoneApplicationPage.Resources>
- <Storyboard x:Name="TitleDispear">
- <DoubleAnimation Duration="0:0:1" To="-158" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
- Storyboard.TargetName="FeaturePivot" d:IsOptimized="True">
- <DoubleAnimation.EasingFunction>
- <CubicEase EasingMode="EaseOut" />
- </DoubleAnimation.EasingFunction>
- </DoubleAnimation>
- </Storyboard>
- <Storyboard x:Name="TitleAppear">
- <DoubleAnimation Duration="0:0:1" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
- Storyboard.TargetName="FeaturePivot" d:IsOptimized="True">
- <DoubleAnimation.EasingFunction>
- <CubicEase EasingMode="EaseOut" />
- </DoubleAnimation.EasingFunction>
- </DoubleAnimation>
- </Storyboard>
- </phone:PhoneApplicationPage.Resources>
- <!---------------code---------------->
- <toolkit:LockablePivot x:Name="FeaturePivot" Title="{Binding Title}" Foreground="{StaticResource PhoneAccentBrush}">
- <toolkit:LockablePivot.RenderTransform>
- <CompositeTransform />
- </toolkit:LockablePivot.RenderTransform>
- <i:Interaction.Triggers>
- <i:EventTrigger EventName="SelectionChanged">
- <cmd:EventToCommand Command="{Binding ChangeSelectionCommand}" CommandParameter="{Binding ElementName=FeaturePivot}" />
- </i:EventTrigger>
- </i:Interaction.Triggers>
- <controls:PivotItem x:Name="StoryPivotItem">
- <controls:PivotItem.RenderTransform>
- <CompositeTransform />
- </controls:PivotItem.RenderTransform>
- <controls:PivotItem.Header>
- <TextBlock Text="{Binding Storys.Title}" FontSize="64" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,10,0,0" Foreground="{StaticResource PhoneAccentBrush}"></TextBlock>
- </controls:PivotItem.Header>
- <lw:StoryList x:Name="HomeTimeLine" DataContext="{Binding Storys}" />
- </controls:PivotItem>
- <!------------code--------------->
- </toolkit:LockablePivot>
在上面的XML文件中定義了兩個Storyboard動畫資源,全屏化時讓FeaturePivot的TranslateY由0->-158,向上溢出,這樣就是實現了header的隱藏,所以TranslateY和margin都是可以隱藏header的,但有一點很大的不同,
TranslateY不會改變UIElement的大小,而Margin會改變,負數等於是拉伸大小。於是這裏問題就產生了,如果光設置TranslateY會導致整個Pivot下方有一部分空白區域。。。所以要着手解決這個問題,也就是這個問題困然了我很久。。。。
看backcode代碼:
- void FullScreenAction()
- {
- if (this.ApplicationBar.IsVisible == false)
- return;
- this.FeaturePivot.Margin = new Thickness(0, 0, 0, -158);
- this.GlobalProgressBar.Margin = new Thickness(0);
- TitleDispear.Begin();
- this.ApplicationBar.IsVisible = false;
- this.FeaturePivot.IsLocked = true;
- this.BackKeyPress += OnFullScreenBackKeyPress;
- }
- void StopFullScreenAction()
- {
- if (this.ApplicationBar.IsVisible == true)
- return;
- this.GlobalProgressBar.Margin = new Thickness(80, 32, 120, 0);
- this.ApplicationBar.IsVisible = true;
- TitleAppear.Begin();
- this.FeaturePivot.Margin = new Thickness(0);
- this.FeaturePivot.IsLocked = false;
- this.BackKeyPress -= OnFullScreenBackKeyPress;
- } //code
這裏我們再start時先對Pivot的Margin的bottom設置爲-158,用戶這時候其實是感知不到pivot的大小變化的,因爲溢出的看不到,接下來在進行動畫的begin操作。就能完美的實現全屏模式了。
慢着,如何觸發全屏這個動作呢,新浪是這麼做的:用戶快速下滑List的時候會開啓,而上拉時關閉。接下來得加上手勢。
我們要用到toolkit中的GestureService行爲了。
前端代碼:
- <controls:PivotItem x:Name="StoryPivotItem">
- <controls:PivotItem.RenderTransform>
- <CompositeTransform />
- </controls:PivotItem.RenderTransform>
- <controls:PivotItem.Header>
- <TextBlock Text="{Binding Storys.Title}" FontSize="64" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,10,0,0" Foreground="{StaticResource PhoneAccentBrush}"></TextBlock>
- </controls:PivotItem.Header>
- <!-- 增加下面的語句 -->
- <toolkit:GestureService.GestureListener>
- <toolkit:GestureListener Flick="OnStoryGestureListenerFlick"/>
- </toolkit:GestureService.GestureListener>
- <!-- END -->
- <lw:StoryList x:Name="HomeTimeLine" DataContext="{Binding Storys}" />
- </controls:PivotItem>
BackCode:
- private void OnStoryGestureListenerFlick(object sender, FlickGestureEventArgs e)
- {
- if (SettingsHelper.GetFullScreenMode() == "0")
- return;
- if (e.Direction == System.Windows.Controls.Orientation.Horizontal) //判斷手勢方向
- return;
- //if (e.Angle < 260 || e.Angle > 280) //角度判斷,可以不用
- // return;
- if (e.VerticalVelocity < 0) //垂直速度判斷
- {
- FullScreenAction();
- }
- else
- {
- StopFullScreenAction();
- }
- }
在前端中加入上面的語句來聲明一個手勢bind,在backcode中進行ActionBind,SettingsHelper.GetFullScreenMode()是設置信息,默認是開啓的。
其他的看註釋。
好,這樣就差不多實現了新浪微博類似的全屏模式。。。出個效果圖(順便宣傳一下來往~~,哇咔咔)
普通界面:
換膚加全屏界面:
Hummm,尼瑪還是全屏神馬的才能看得更多嘛!!
http://www.itboat.net/thread-38914-1-1.html