借鉴了 段博琼 大哥写的导航滑动,自己实现了一个类似安卓 IOS 导航滑动条
支持等比例 分割 tabView 支持动画滑动
效果如下图
WYGrid 你可以想象一个GridView itemsWrapGridPanel.Orientation = Orientation.Vertical; 垂直方向的控件
自定义一个项高 ItemHeight 并绑定到最高属性
var itemsWrapGridPanel = ItemsPanelRoot as ItemsWrapGrid; var b = new Binding() { Source = this, Path = new PropertyPath("ItemHeight") }; if (itemsWrapGridPanel != null) { itemsWrapGridPanel.Orientation = Orientation.Vertical; } this.SetBinding(MaxHeightProperty, b);
容器样式来自于 GridViewItem styles and templates
xaml实现
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <ctl:WYGrid x:Name="PART_ListViewStateName" Background="RoyalBlue" Padding="0" Margin="0" BorderThickness="0" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollMode="Disabled" ItemHeight="45" ItemTemplate="{StaticResource DT_Pivot}" ItemsSource="{Binding MyItemSources}"> <ctl:WYGrid.ItemContainerStyle> <Style TargetType="GridViewItem"> <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" /> <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" /> <Setter Property="Background" Value="Transparent" /> <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" /> <Setter Property="TabNavigation" Value="Local" /> <Setter Property="IsHoldingEnabled" Value="True" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="Margin" Value="0" /> <Setter Property="MinWidth" Value="{ThemeResource GridViewItemMinWidth}" /> <Setter Property="MinHeight" Value="{ThemeResource GridViewItemMinHeight}" /> <Setter Property="AllowDrop" Value="False" /> <Setter Property="UseSystemFocusVisuals" Value="True" /> <Setter Property="FocusVisualMargin" Value="-2" /> <Setter Property="FocusVisualPrimaryBrush" Value="{ThemeResource SystemControlFocusVisualPrimaryBrush}" /> <Setter Property="FocusVisualPrimaryThickness" Value="2" /> <Setter Property="FocusVisualSecondaryBrush" Value="{ThemeResource SystemControlFocusVisualSecondaryBrush}" /> <Setter Property="FocusVisualSecondaryThickness" Value="1" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="GridViewItem"> <Grid x:Name="ContentBorder" Control.IsTemplateFocusTarget="True" BorderThickness="0" RenderTransformOrigin="0.5,0.5"> <Grid.RenderTransform> <ScaleTransform x:Name="ContentBorderScale" /> </Grid.RenderTransform> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="FocusStates"> <VisualState x:Name="Focused"/> <VisualState x:Name="Unfocused"/> </VisualStateGroup> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="PointerOver"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentBorder" Storyboard.TargetProperty="FocusVisualSecondaryBrush"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListLowBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentBorder" Storyboard.TargetProperty="FocusVisualSecondaryThickness"> <DiscreteObjectKeyFrame KeyTime="0" Value="2" /> </ObjectAnimationUsingKeyFrames> <PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" /> </Storyboard> </VisualState> <VisualState x:Name="Pressed"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentBorder" Storyboard.TargetProperty="FocusVisualSecondaryBrush"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListMediumBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentBorder" Storyboard.TargetProperty="FocusVisualSecondaryThickness"> <DiscreteObjectKeyFrame KeyTime="0" Value="2" /> </ObjectAnimationUsingKeyFrames> <PointerDownThemeAnimation TargetName="ContentPresenter" /> </Storyboard> </VisualState> <VisualState x:Name="Selected"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentBorder" Storyboard.TargetProperty="FocusVisualSecondaryBrush"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentBorder" Storyboard.TargetProperty="FocusVisualSecondaryThickness"> <DiscreteObjectKeyFrame KeyTime="0" Value="2" /> </ObjectAnimationUsingKeyFrames> <PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" /> </Storyboard> </VisualState> <VisualState x:Name="PointerOverSelected"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentBorder" Storyboard.TargetProperty="FocusVisualSecondaryBrush"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListAccentMediumBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentBorder" Storyboard.TargetProperty="FocusVisualSecondaryThickness"> <DiscreteObjectKeyFrame KeyTime="0" Value="2" /> </ObjectAnimationUsingKeyFrames> <PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" /> </Storyboard> </VisualState> <VisualState x:Name="PressedSelected"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentBorder" Storyboard.TargetProperty="FocusVisualSecondaryBrush"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListAccentHighBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentBorder" Storyboard.TargetProperty="FocusVisualSecondaryThickness"> <DiscreteObjectKeyFrame KeyTime="0" Value="2" /> </ObjectAnimationUsingKeyFrames> <PointerDownThemeAnimation TargetName="ContentPresenter" /> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="DisabledStates"> <VisualState x:Name="Enabled" /> <VisualState x:Name="Disabled"> <Storyboard> <DoubleAnimation Storyboard.TargetName="ContentBorder" Storyboard.TargetProperty="Opacity" Duration="0" To="{ThemeResource ListViewItemDisabledThemeOpacity}" /> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <ContentPresenter x:Name="ContentPresenter" VerticalAlignment="Center" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Background="SkyBlue" FontSize="20" Margin="0,10,0,10"/> <Rectangle x:Name="PlaceholderRect" Visibility="Visible" Fill="Red" Height="2" Width="40" VerticalAlignment="Bottom"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </ctl:WYGrid.ItemContainerStyle> </ctl:WYGrid> <Rectangle x:Name="PART_RectStateName" Fill="Red" Height="2" Width="130" Grid.Row="1" Opacity="1" Margin="0,-2,0,0" HorizontalAlignment="Left" > <Rectangle.RenderTransform> <TranslateTransform/> </Rectangle.RenderTransform> </Rectangle> </Grid>
基本实现思路是
初始化的时候 PivotItemLoading 来初始化导航条的位置
PART_RectStateName 显示动画 透明为1, gridview 里面的 PlaceholderRect 透明 为0
当点击的时候 SelectionChanged 被call 查找ContentPresenter 和 Rectangle 来确定位置和宽度,启动动画,之后让
PART_RectStateName 显示动画 透明为0, gridview 里面的 PlaceholderRect 透明 为1
下面是动画的代码,思路清楚了接下来很快就做好了。
private Storyboard StoryBordTemp(double formW, double toW, Point newPoint, Point oldPoint) { var storyBoard = new Storyboard(); var extendAnimation = new DoubleAnimation { Duration = new Duration(TimeSpan.FromSeconds(0.5)), From = formW, To = toW, EnableDependentAnimation = true }; QuarticEase easing = new QuarticEase(); easing.EasingMode = EasingMode.EaseOut; easing.Ease(0.3); extendAnimation.EasingFunction = easing; Storyboard.SetTarget(extendAnimation, _rectangle); Storyboard.SetTargetProperty(extendAnimation, "Width"); var xAnimation = new DoubleAnimation { Duration = new Duration(TimeSpan.FromSeconds(0.5)), From = newPoint.X, To = oldPoint.X, EnableDependentAnimation = true }; QuarticEase xEasing = new QuarticEase(); xEasing.EasingMode = EasingMode.EaseOut; xEasing.Ease(0.3); xAnimation.EasingFunction = xEasing; Storyboard.SetTarget(xAnimation, _rectangle); Storyboard.SetTargetProperty(xAnimation, "(UIElement.RenderTransform).(TranslateTransform.X)"); storyBoard.Children.Add(extendAnimation); storyBoard.Children.Add(xAnimation); storyBoard.Begin(); return storyBoard; }