Pivot 是 Windows Phone 最常用的一种控件,用户可以通过滑动来切换不同的视图,而切换视图的时候 PivotItem Header (默认)是会变化的——在 WP8.1 的时候是会变到第一个并且高亮显示。而 WP 微信则是采用固定的四个图标当作 Header,而这种效果并不是控件的默认属性,那么我们该怎么实现这个效果呢?
改 Header 的 Style
是一种方法,但是这里我介绍另一种方法(这篇博文用的是 WP8.1 的项目,UWP 也同样适用喔~):
去掉 PivotItem
自己的 Header
,用别的容器来装,然后通过 Pivot 的 SelectionChanged
事件来实现样式变化。
这里我们把页面分成两部分,上半部分用来放 Header
,余下的部分全用来放 PivotItem
,xaml 里这样写:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid Grid.Row="0"> <!-- 这里用来放 Header --> </Grid> <Grid Grid.Row="1"> <!-- 这里用来放 PivotItem--> </Grid> </Grid>
先把准备好的图标加进项目里,我这里准备了四组图标,每组两个(一明一暗,其中暗的以 _
作为文件名的结尾),我把这些图标放到 /Asset/PivotHeader/Image
里了。
把 Header 所在那个 Grid
里等分成四列,每列一个 StackPanel
,里面放我们 Header 的图标、文字什么的。
<Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid Grid.Column="0"> <!-- Tapped 事件是为了让用户点击 Header 的时候也能实现切换 --> <StackPanel Tapped="StackPanel0_Tapped" x:Name="Windows"> <!-- 先让它装入暗的图标,选中的时候再变亮,下面的同理 --> <Image x:Name="Windows_Img" Source="ms-appx:///Assets/PivotHeaderImage/Windows_.png" Width="50" Height="50"/> <!-- 文字的颜色也同理 --> <TextBlock x:Name="Windows_Txt" Foreground="#CCCCCC" FontSize="15" TextAlignment="Center">Windows</TextBlock> </StackPanel> </Grid> <Grid Grid.Column="1"> <StackPanel Tapped="StackPanel1_Tapped" x:Name="Office"> <Image x:Name="Office_Img" Source="ms-appx:///Assets/PivotHeaderImage/Office_.png" Width="50" Height="50"/> <TextBlock x:Name="Office_Txt" Foreground="#CCCCCC" FontSize="15" TextAlignment="Center">Office</TextBlock> </StackPanel> </Grid> <Grid Grid.Column="2"> <StackPanel Tapped="StackPanel2_Tapped" x:Name="OneDrive"> <Image x:Name="OneDrive_Img" Source="ms-appx:///Assets/PivotHeaderImage/OneDrive_.png" Width="50" Height="50"/> <TextBlock x:Name="OneDrive_Txt" Foreground="#CCCCCC" FontSize="15" TextAlignment="Center">OneDrive</TextBlock> </StackPanel> </Grid> <Grid Grid.Column="3"> <StackPanel Tapped="StackPanel3_Tapped" x:Name="Store"> <Image x:Name="Store_Img" Source="ms-appx:///Assets/PivotHeaderImage/Store_.png" Width="50" Height="50"/> <TextBlock x:Name="Store_Txt" Foreground="#CCCCCC" FontSize="15" TextAlignment="Center">Store</TextBlock> </StackPanel> </Grid>
效果是这样的:
准备好了 Header,下面我们要添加四个(对应四个 Header) PivotItem 了。在页面下半部分那个 Grid 里添加一个 Pivot:
<Pivot x:Name="MyPivot" SelectionChanged="MyPivot_SelectionChanged"> <PivotItem> <Grid> <!-- PivotItem0 --> </Grid> </PivotItem> <PivotItem> <Grid> <!-- PivotItem1 --> </Grid> </PivotItem> <PivotItem> <Grid> <!-- PivotItem2 --> </Grid> </PivotItem> <PivotItem> <Grid> <!-- PivotItem3 --> </Grid> </PivotItem> </Pivot>
首先我们要先有一个变量,用来记录 切换前
Pivot 的 index
,所以我们先定义一个整型变量并让其初始化为 ,
int PreIndex = 0;
;为什么要有这个变量呢,有了它之后我们就可以在切换时 直接准确
地把切换前的 Header 变成暗的,这样效率会略有提高(我猜的 -_-|||)。
然后添加 SelectionChanged
事件处理程序 MyPivot_SelectionChanged
// MyPivot 的前一个索引 int PreIndex = 0; private void MyPivot_SelectionChanged(object sender, SelectionChangedEventArgs e) { // 将变换前的 Header 变“暗” switch(PreIndex) { case 0: Windows_Img.Source = new BitmapImage(new Uri("ms-appx:///Assets/PivotHeaderImage/Windows_.png")); Windows_Txt.Foreground = new SolidColorBrush(Color.FromArgb(255, 128, 128, 128)); break; case 1: Office_Img.Source = new BitmapImage(new Uri("ms-appx:///Assets/PivotHeaderImage/Office_.png")); Office_Txt.Foreground = new SolidColorBrush(Color.FromArgb(255, 128, 128, 128)); break; case 2: OneDrive_Img.Source = new BitmapImage(new Uri("ms-appx:///Assets/PivotHeaderImage/OneDrive_.png")); OneDrive_Txt.Foreground = new SolidColorBrush(Color.FromArgb(255, 128, 128, 128)); break; case 3: Store_Img.Source = new BitmapImage(new Uri("ms-appx:///Assets/PivotHeaderImage/Store_.png")); Store_Txt.Foreground = new SolidColorBrush(Color.FromArgb(255, 128, 128, 128)); break; } // 当前的 Index 将会变成“切换前”的 Index PreIndex = (sender as Pivot).SelectedIndex; // 将当前的 Header 变“亮” switch ((sender as Pivot).SelectedIndex) { case 0: Windows_Img.Source = new BitmapImage(new Uri("ms-appx:///Assets/PivotHeaderImage/Windows.png")); Windows_Txt.Foreground = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)); break; case 1: Office_Img.Source = new BitmapImage(new Uri("ms-appx:///Assets/PivotHeaderImage/Office.png")); Office_Txt.Foreground = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)); break; case 2: OneDrive_Img.Source = new BitmapImage(new Uri("ms-appx:///Assets/PivotHeaderImage/OneDrive.png")); OneDrive_Txt.Foreground = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)); break; case 3: Store_Img.Source = new BitmapImage(new Uri("ms-appx:///Assets/PivotHeaderImage/Store.png")); Store_Txt.Foreground = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)); break; } }
别忘了添加一下 Header 的 Tapped 事件
private void StackPanel0_Tapped(object sender, TappedRoutedEventArgs e) { MyPivot.SelectedIndex = 0; } private void StackPanel1_Tapped(object sender, TappedRoutedEventArgs e) { MyPivot.SelectedIndex = 1; } private void StackPanel2_Tapped(object sender, TappedRoutedEventArgs e) { MyPivot.SelectedIndex = 2; } private void StackPanel3_Tapped(object sender, TappedRoutedEventArgs e) { MyPivot.SelectedIndex = 3; }
好了,看一下效果吧~
诶?Header 的图标会闪?没错,不是你的网络啊浏览器啊什么的有问题,是真的会闪!因为每次切换时都要加载图片,这样会略有延迟,可是微信的是没有闪动的,切换很流畅的!
先放张图看下优化后的效果:
很流畅对吧(我没有对这个 gif 做手脚,是真的优化过~)。
要达到这种流畅的效果,我们需要将每组两个图标都先加载进来,怎么实现呢,用两个 StackPanel
分别装 亮
和 暗
时的 Header,不同状态显示对应的 StackPanel
就行了嘛!
那么我们需要修改一下上半部分的 Grid
:
<Grid Grid.Column="0"> <StackPanel Tapped="StackPanel0_Tapped" x:Name="Windows" Visibility="Collapsed"> <Image Source="ms-appx:///Assets/PivotHeaderImage/Windows.png" Width="50" Height="50"/> <TextBlock FontSize="15" TextAlignment="Center">Windows</TextBlock> </StackPanel> <StackPanel Tapped="StackPanel0_Tapped" x:Name="Windows_"> <Image Source="ms-appx:///Assets/PivotHeaderImage/Windows_.png" Width="50" Height="50"/> <TextBlock FontSize="15" TextAlignment="Center" Foreground="Gray">Windows</TextBlock> </StackPanel> </Grid> <Grid Grid.Column="1"> <StackPanel Tapped="StackPanel1_Tapped" x:Name="Office" Visibility="Collapsed"> <Image Source="ms-appx:///Assets/PivotHeaderImage/Office.png" Width="50" Height="50"/> <TextBlock FontSize="15" TextAlignment="Center">Office</TextBlock> </StackPanel> <StackPanel Tapped="StackPanel1_Tapped" x:Name="Office_"> <Image Source="ms-appx:///Assets/PivotHeaderImage/Office_.png" Width="50" Height="50"/> <TextBlock FontSize="15" TextAlignment="Center" Foreground="Gray">Office</TextBlock> </StackPanel> </Grid> <Grid Grid.Column="2"> <StackPanel Tapped="StackPanel2_Tapped" x:Name="OneDrive" Visibility="Collapsed"> <Image Source="ms-appx:///Assets/PivotHeaderImage/OneDrive.png" Width="50" Height="50"/> <TextBlock FontSize="15" TextAlignment="Center">OneDrive</TextBlock> </StackPanel> <StackPanel Tapped="StackPanel2_Tapped" x:Name="OneDrive_"> <Image Source="ms-appx:///Assets/PivotHeaderImage/OneDrive_.png" Width="50" Height="50"/> <TextBlock FontSize="15" TextAlignment="Center" Foreground="Gray">OneDrive</TextBlock> </StackPanel> </Grid> <Grid Grid.Column="3"> <StackPanel Tapped="StackPanel3_Tapped" x:Name="Store" Visibility="Collapsed"> <Image Source="ms-appx:///Assets/PivotHeaderImage/Store.png" Width="50" Height="50"/> <TextBlock FontSize="15" TextAlignment="Center" x:Name="SPT3">Store</TextBlock> </StackPanel> <StackPanel Tapped="StackPanel3_Tapped" x:Name="Store_"> <Image Source="ms-appx:///Assets/PivotHeaderImage/Store_.png" Width="50" Height="50"/> <TextBlock FontSize="15" TextAlignment="Center" Foreground="Gray">Store</TextBlock> </StackPanel> </Grid>
然后对应修改一下 SelectionChanged
private void MyPivot_SelectionChanged(object sender, SelectionChangedEventArgs e) { switch(PreIndex) { case 0: Windows.Visibility = Visibility.Collapsed; Windows_.Visibility = Visibility.Visible; break; case 1: Office.Visibility = Visibility.Collapsed; Office_.Visibility = Visibility.Visible; break; case 2: OneDrive.Visibility = Visibility.Collapsed; OneDrive_.Visibility = Visibility.Visible; break; case 3: Store.Visibility = Visibility.Collapsed; Store_.Visibility = Visibility.Visible; break; } PreIndex = (sender as Pivot).SelectedIndex; switch ((sender as Pivot).SelectedIndex) { case 0: Windows_.Visibility = Visibility.Collapsed; Windows.Visibility = Visibility.Visible; break; case 1: Office_.Visibility = Visibility.Collapsed; Office.Visibility = Visibility.Visible; break; case 2: OneDrive_.Visibility = Visibility.Collapsed; OneDrive.Visibility = Visibility.Visible; break; case 3: Store_.Visibility = Visibility.Collapsed; Store.Visibility = Visibility.Visible; break; } }
好了,运行一下看看吧~
前几天看 MSDN 博客侠
的文章《 Win 10 UWP开发系列:设置AppBarButton的图标 》看到一款制作图标的神器—— Merto Studio 4 ,本文用的图标就是直接从这个软件里导出来的~