昨天想在 uwp 上实现,在 SplitView 控件的左侧,通过手指滑动打开 SplitView 的 Pane 面板,
而不仅仅是通过 “汉堡按钮” 点击打开。
在 stackoverflow 看到一个帖子, 有讨论一个方案,然后看了一下里面的一个 github 工程,实现了
SwipeableSplitView(工程连接), 不过下载代码分析了一下,代码量太大,通过继承 SplitView 控件,添加很多 xaml 和
C# 代码,有点复杂了。于是想了一个简单的方式,直接控制 SplitView 中 Template 的 CompositeTransform 和
VisualTransition 属性就可以了,几十行 C# 代码就能搞定。
1、运行效果 (VS2015 创建的 win10 UWP 工程)
1)在 phone上:
2)在 win10 pc 上:
2、分析 SplitView 控件的模板(只用来分析,并不使用)
1)在空白页面中,添加一个 SplitView,在文档大纲中,右键单击 SplitView 控件,选择编辑副本:
2)在生成的代码中,可以看到,当前 SplitView 控件的组成部分:
这里重点使用 PaneRoot 中的 PaneTransform 属性,和 视觉状态属性中的 VisualTransition From="Closed" To="OpenOverlayLeft" 属性。
VS 所有生成的 SplitView 的 Template 代码:
1 <ControlTemplate x:Key="SplitViewControlTemplate1" TargetType="SplitView"> 2 <Grid Background="{TemplateBinding Background}"> 3 <VisualStateManager.VisualStateGroups> 4 <VisualStateGroup x:Name="DisplayModeStates"> 5 <VisualStateGroup.Transitions> 6 <VisualTransition From="Closed" To="OpenOverlayLeft"> 7 <Storyboard> 8 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 9 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 10 </ObjectAnimationUsingKeyFrames> 11 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 12 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 13 </ObjectAnimationUsingKeyFrames> 14 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneTransform" Storyboard.TargetProperty="TranslateX"> 15 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.NegativeOpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 16 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/> 17 </DoubleAnimationUsingKeyFrames> 18 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX"> 19 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 20 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/> 21 </DoubleAnimationUsingKeyFrames> 22 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility"> 23 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 24 </ObjectAnimationUsingKeyFrames> 25 </Storyboard> 26 </VisualTransition> 27 <VisualTransition From="Closed" To="OpenOverlayRight"> 28 <Storyboard> 29 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 30 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 31 </ObjectAnimationUsingKeyFrames> 32 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment"> 33 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/> 34 </ObjectAnimationUsingKeyFrames> 35 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment"> 36 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/> 37 </ObjectAnimationUsingKeyFrames> 38 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 39 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 40 </ObjectAnimationUsingKeyFrames> 41 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneTransform" Storyboard.TargetProperty="TranslateX"> 42 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 43 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/> 44 </DoubleAnimationUsingKeyFrames> 45 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX"> 46 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.NegativeOpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 47 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/> 48 </DoubleAnimationUsingKeyFrames> 49 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility"> 50 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 51 </ObjectAnimationUsingKeyFrames> 52 </Storyboard> 53 </VisualTransition> 54 <VisualTransition From="ClosedCompactLeft" To="OpenCompactOverlayLeft"> 55 <Storyboard> 56 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width"> 57 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 58 </ObjectAnimationUsingKeyFrames> 59 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.Column)"> 60 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 61 </ObjectAnimationUsingKeyFrames> 62 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 63 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 64 </ObjectAnimationUsingKeyFrames> 65 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 66 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 67 </ObjectAnimationUsingKeyFrames> 68 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 69 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 70 </ObjectAnimationUsingKeyFrames> 71 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX"> 72 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.NegativeOpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 73 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/> 74 </DoubleAnimationUsingKeyFrames> 75 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility"> 76 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 77 </ObjectAnimationUsingKeyFrames> 78 </Storyboard> 79 </VisualTransition> 80 <VisualTransition From="ClosedCompactRight" To="OpenCompactOverlayRight"> 81 <Storyboard> 82 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width"> 83 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="*"/> 84 </ObjectAnimationUsingKeyFrames> 85 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition2" Storyboard.TargetProperty="Width"> 86 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 87 </ObjectAnimationUsingKeyFrames> 88 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 89 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 90 </ObjectAnimationUsingKeyFrames> 91 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 92 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 93 </ObjectAnimationUsingKeyFrames> 94 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment"> 95 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/> 96 </ObjectAnimationUsingKeyFrames> 97 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment"> 98 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/> 99 </ObjectAnimationUsingKeyFrames> 100 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 101 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 102 </ObjectAnimationUsingKeyFrames> 103 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX"> 104 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.OpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 105 <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/> 106 </DoubleAnimationUsingKeyFrames> 107 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility"> 108 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 109 </ObjectAnimationUsingKeyFrames> 110 </Storyboard> 111 </VisualTransition> 112 <VisualTransition From="OpenOverlayLeft" To="Closed"> 113 <Storyboard> 114 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 115 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 116 </ObjectAnimationUsingKeyFrames> 117 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 118 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 119 </ObjectAnimationUsingKeyFrames> 120 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneTransform" Storyboard.TargetProperty="TranslateX"> 121 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.NegativeOpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 122 </DoubleAnimationUsingKeyFrames> 123 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX"> 124 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 125 </DoubleAnimationUsingKeyFrames> 126 </Storyboard> 127 </VisualTransition> 128 <VisualTransition From="OpenOverlayRight" To="Closed"> 129 <Storyboard> 130 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 131 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 132 </ObjectAnimationUsingKeyFrames> 133 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment"> 134 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/> 135 </ObjectAnimationUsingKeyFrames> 136 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment"> 137 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/> 138 </ObjectAnimationUsingKeyFrames> 139 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 140 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 141 </ObjectAnimationUsingKeyFrames> 142 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneTransform" Storyboard.TargetProperty="TranslateX"> 143 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 144 </DoubleAnimationUsingKeyFrames> 145 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX"> 146 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.NegativeOpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 147 </DoubleAnimationUsingKeyFrames> 148 </Storyboard> 149 </VisualTransition> 150 <VisualTransition From="OpenCompactOverlayLeft" To="ClosedCompactLeft"> 151 <Storyboard> 152 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width"> 153 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 154 </ObjectAnimationUsingKeyFrames> 155 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.Column)"> 156 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 157 </ObjectAnimationUsingKeyFrames> 158 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 159 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 160 </ObjectAnimationUsingKeyFrames> 161 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 162 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 163 </ObjectAnimationUsingKeyFrames> 164 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 165 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 166 </ObjectAnimationUsingKeyFrames> 167 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX"> 168 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0"/> 169 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.NegativeOpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 170 </DoubleAnimationUsingKeyFrames> 171 </Storyboard> 172 </VisualTransition> 173 <VisualTransition From="OpenCompactOverlayRight" To="ClosedCompactRight"> 174 <Storyboard> 175 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width"> 176 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="*"/> 177 </ObjectAnimationUsingKeyFrames> 178 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition2" Storyboard.TargetProperty="Width"> 179 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 180 </ObjectAnimationUsingKeyFrames> 181 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 182 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 183 </ObjectAnimationUsingKeyFrames> 184 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 185 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 186 </ObjectAnimationUsingKeyFrames> 187 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment"> 188 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/> 189 </ObjectAnimationUsingKeyFrames> 190 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment"> 191 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/> 192 </ObjectAnimationUsingKeyFrames> 193 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 194 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 195 </ObjectAnimationUsingKeyFrames> 196 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX"> 197 <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0"/> 198 <SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding TemplateSettings.OpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 199 </DoubleAnimationUsingKeyFrames> 200 </Storyboard> 201 </VisualTransition> 202 </VisualStateGroup.Transitions> 203 <VisualState x:Name="Closed"/> 204 <VisualState x:Name="ClosedCompactLeft"> 205 <Storyboard> 206 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width"> 207 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 208 </ObjectAnimationUsingKeyFrames> 209 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.Column)"> 210 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 211 </ObjectAnimationUsingKeyFrames> 212 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 213 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 214 </ObjectAnimationUsingKeyFrames> 215 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 216 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 217 </ObjectAnimationUsingKeyFrames> 218 <DoubleAnimation Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX" To="{Binding TemplateSettings.NegativeOpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}" Duration="0:0:0"/> 219 </Storyboard> 220 </VisualState> 221 <VisualState x:Name="ClosedCompactRight"> 222 <Storyboard> 223 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width"> 224 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="*"/> 225 </ObjectAnimationUsingKeyFrames> 226 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition2" Storyboard.TargetProperty="Width"> 227 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 228 </ObjectAnimationUsingKeyFrames> 229 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 230 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 231 </ObjectAnimationUsingKeyFrames> 232 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 233 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 234 </ObjectAnimationUsingKeyFrames> 235 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 236 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="2"/> 237 </ObjectAnimationUsingKeyFrames> 238 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment"> 239 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/> 240 </ObjectAnimationUsingKeyFrames> 241 <DoubleAnimation Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX" To="{Binding TemplateSettings.OpenPaneLengthMinusCompactLength, RelativeSource={RelativeSource Mode=TemplatedParent}}" Duration="0:0:0"/> 242 </Storyboard> 243 </VisualState> 244 <VisualState x:Name="OpenOverlayLeft"> 245 <Storyboard> 246 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 247 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 248 </ObjectAnimationUsingKeyFrames> 249 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 250 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 251 </ObjectAnimationUsingKeyFrames> 252 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility"> 253 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 254 </ObjectAnimationUsingKeyFrames> 255 </Storyboard> 256 </VisualState> 257 <VisualState x:Name="OpenOverlayRight"> 258 <Storyboard> 259 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 260 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 261 </ObjectAnimationUsingKeyFrames> 262 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment"> 263 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/> 264 </ObjectAnimationUsingKeyFrames> 265 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 266 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 267 </ObjectAnimationUsingKeyFrames> 268 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment"> 269 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/> 270 </ObjectAnimationUsingKeyFrames> 271 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility"> 272 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 273 </ObjectAnimationUsingKeyFrames> 274 </Storyboard> 275 </VisualState> 276 <VisualState x:Name="OpenInlineLeft"> 277 <Storyboard> 278 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.Column)"> 279 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 280 </ObjectAnimationUsingKeyFrames> 281 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 282 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 283 </ObjectAnimationUsingKeyFrames> 284 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 285 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 286 </ObjectAnimationUsingKeyFrames> 287 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 288 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 289 </ObjectAnimationUsingKeyFrames> 290 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 291 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 292 </ObjectAnimationUsingKeyFrames> 293 </Storyboard> 294 </VisualState> 295 <VisualState x:Name="OpenInlineRight"> 296 <Storyboard> 297 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width"> 298 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="*"/> 299 </ObjectAnimationUsingKeyFrames> 300 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition2" Storyboard.TargetProperty="Width"> 301 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.OpenPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 302 </ObjectAnimationUsingKeyFrames> 303 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 304 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 305 </ObjectAnimationUsingKeyFrames> 306 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 307 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 308 </ObjectAnimationUsingKeyFrames> 309 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="(Grid.Column)"> 310 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 311 </ObjectAnimationUsingKeyFrames> 312 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 313 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 314 </ObjectAnimationUsingKeyFrames> 315 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment"> 316 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/> 317 </ObjectAnimationUsingKeyFrames> 318 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 319 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 320 </ObjectAnimationUsingKeyFrames> 321 </Storyboard> 322 </VisualState> 323 <VisualState x:Name="OpenCompactOverlayLeft"> 324 <Storyboard> 325 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width"> 326 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 327 </ObjectAnimationUsingKeyFrames> 328 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.Column)"> 329 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 330 </ObjectAnimationUsingKeyFrames> 331 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 332 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 333 </ObjectAnimationUsingKeyFrames> 334 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 335 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 336 </ObjectAnimationUsingKeyFrames> 337 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 338 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 339 </ObjectAnimationUsingKeyFrames> 340 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility"> 341 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 342 </ObjectAnimationUsingKeyFrames> 343 </Storyboard> 344 </VisualState> 345 <VisualState x:Name="OpenCompactOverlayRight"> 346 <Storyboard> 347 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition1" Storyboard.TargetProperty="Width"> 348 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="*"/> 349 </ObjectAnimationUsingKeyFrames> 350 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ColumnDefinition2" Storyboard.TargetProperty="Width"> 351 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.CompactPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 352 </ObjectAnimationUsingKeyFrames> 353 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(Grid.ColumnSpan)"> 354 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="1"/> 355 </ObjectAnimationUsingKeyFrames> 356 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> 357 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 358 </ObjectAnimationUsingKeyFrames> 359 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="HorizontalAlignment"> 360 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Right"/> 361 </ObjectAnimationUsingKeyFrames> 362 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="HorizontalAlignment"> 363 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Left"/> 364 </ObjectAnimationUsingKeyFrames> 365 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> 366 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 367 </ObjectAnimationUsingKeyFrames> 368 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility"> 369 <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> 370 </ObjectAnimationUsingKeyFrames> 371 </Storyboard> 372 </VisualState> 373 </VisualStateGroup> 374 </VisualStateManager.VisualStateGroups> 375 376 <Grid.ColumnDefinitions> 377 <ColumnDefinition x:Name="ColumnDefinition1" Width="{Binding TemplateSettings.OpenPaneGridLength, FallbackValue=0, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> 378 <ColumnDefinition x:Name="ColumnDefinition2" Width="*"/> 379 </Grid.ColumnDefinitions> 380 381 <!-- Content Area --> 382 <Grid x:Name="ContentRoot" Grid.ColumnSpan="2"> 383 <Border Child="{TemplateBinding Content}"/> 384 <Rectangle x:Name="LightDismissLayer" Fill="Transparent" Visibility="Collapsed"/> 385 </Grid> 386 387 <!-- Pane Content Area--> 388 <Grid 389 x:Name="PaneRoot" 390 Grid.ColumnSpan="2" 391 HorizontalAlignment="Left" 392 Visibility="Collapsed" 393 Background="{TemplateBinding PaneBackground}" 394 Width="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"> 395 <Grid.Clip> 396 <RectangleGeometry x:Name="PaneClipRectangle"> 397 <RectangleGeometry.Transform> 398 <CompositeTransform x:Name="PaneClipRectangleTransform"/> 399 </RectangleGeometry.Transform> 400 </RectangleGeometry> 401 </Grid.Clip> 402 <Grid.RenderTransform> 403 <CompositeTransform x:Name="PaneTransform"/> 404 </Grid.RenderTransform> 405 <Border Child="{TemplateBinding Pane}"/> 406 <Rectangle 407 x:Name="HCPaneBorder" 408 x:DeferLoadStrategy="Lazy" 409 Visibility="Collapsed" 410 Fill="{ThemeResource SystemControlForegroundTransparentBrush}" 411 Width="1" 412 HorizontalAlignment="Right"/> 413 </Grid> 414 </Grid> 415 </ControlTemplate>
3、在 xaml 页面中,添加一个 Border 控件,显示在窗口的最左侧,检测用户的滑动手势
<!--屏幕左侧手势检测区域, 在实际代码中可以把 Opacity 设置为 0 --> <Border Grid.RowSpan="2" ManipulationMode="TranslateX" ManipulationCompleted="Border_ManipulationCompleted" ManipulationDelta="Border_ManipulationDelta" Width="36" Opacity=".5" Background="Green" HorizontalAlignment="Left"/>
通过注册 Manipulation 事件,可以检测底层触摸事件。这个 Border 即为上面 gif 图片中,绿色的部分。
MainPage.xaml 页面中,全部的 xaml :
<Page x:Class="SwipeableSplitView.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:SwipeableSplitView" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" RequestedTheme="Light"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" > <SplitView x:Name="MySplitView" DisplayMode="CompactInline" IsPaneOpen="True" IsTabStop="False" PaneBackground="#88440000" Loaded="MySplitView_Loaded" CompactPaneLength="88" OpenPaneLength="280" > <SplitView.Pane> <ListView Margin="0,60,0,0"> <ListView.Resources> <Style TargetType="StackPanel"> <Setter Property="Orientation" Value="Horizontal"/> <Setter Property="Margin" Value="20,20"/> </Style> <Style TargetType="TextBlock"> <Setter Property="Margin" Value="50,0,0,0"/> <Setter Property="Foreground" Value="White"/> <Setter Property="FontSize" Value="22"/> </Style> <Style TargetType="FontIcon"> <Setter Property="Foreground" Value="White"/> <Setter Property="FontSize" Value="30"/> </Style> </ListView.Resources> <StackPanel> <FontIcon Glyph=""/> <TextBlock Text="页面 1 "/> </StackPanel> <StackPanel> <FontIcon Glyph="" /> <TextBlock Text="页面 2 "/> </StackPanel> <StackPanel> <FontIcon Glyph=""/> <TextBlock Text="页面 3 "/> </StackPanel> </ListView> </SplitView.Pane> <Grid> <!--<Frame/>--> <TextBlock Text="当窗口宽度最小时,通过鼠标或者手指,从窗口最左侧向右滑动,则打开 SplitView.Pane " Width="250" FontSize="30" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center"/> <!--屏幕左侧手势检测区域, 在实际代码中可以把 Opacity 设置为 0 --> <Border Grid.RowSpan="2" ManipulationMode="TranslateX" ManipulationCompleted="Border_ManipulationCompleted" ManipulationDelta="Border_ManipulationDelta" Width="36" Opacity=".5" Background="Green" HorizontalAlignment="Left"/> <!--显示 Debug 数据--> <Border HorizontalAlignment="Right" Margin="20" Background="Gray" VerticalAlignment="Top"> <TextBlock x:Name="txtDebug" Text="debug" FontSize="30" Foreground="GreenYellow" Margin="10"/> </Border> </Grid> </SplitView> <!--汉堡按钮--> <CheckBox IsChecked="{Binding IsPaneOpen,ElementName=MySplitView, Mode=TwoWay}" IsThreeState="False" Height="40" Width="40" VerticalAlignment="Top" HorizontalAlignment="Left" Style="{StaticResource CheckBoxStyle1}"> <FontIcon Glyph="" Foreground="White" FontSize="25" /> </CheckBox> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="visualState"> <VisualState x:Name="wide"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="1024" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="MySplitView.DisplayMode" Value="CompactInline" /> <Setter Target="MySplitView.IsPaneOpen" Value="True" /> </VisualState.Setters> </VisualState> <VisualState x:Name="meddium"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="548" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="MySplitView.DisplayMode" Value="CompactInline" /> <Setter Target="MySplitView.IsPaneOpen" Value="False" /> </VisualState.Setters> </VisualState> <VisualState x:Name="narrow"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="MySplitView.DisplayMode" Value="Overlay" /> <Setter Target="MySplitView.IsPaneOpen" Value="False" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </Page>
4、在 MainPage.xaml.cs 页面中
1)分析:当 SplitView.IsPaneOpen 设置为 true 时, Pane 的 CompositeTransform 的 TranslateX 的数值变化
在 SplitView 的 Loaded 事件中,把数值打印出来:
// Debug 数据输出,左侧面板 TranslateX 的变化 private void MySplitView_Loaded(object sender, RoutedEventArgs e) { #if DEBUG Grid grid = Utility.FindVisualChild<Grid>(MySplitView); Binding bind = new Binding(); bind.Path = new PropertyPath("TranslateX"); bind.Source = (grid.FindName("PaneRoot") as Grid).RenderTransform as CompositeTransform; // 显示到 TextBlock 上 txtDebug.SetBinding(TextBlock.TextProperty, bind); txtDebug.RegisterPropertyChangedCallback(TextBlock.TextProperty, (dependencyObject, dependencyProperty) => { // 注册 TextBlock.TextProperty 属性回调事件,显示到输出窗口 Debug.WriteLine("txtDebug.Text ; " + txtDebug.Text); }); #endif }
在窄窗口模式下,点击 汉堡按钮,查看输出窗口,数值从 280 (SplitView.OpenPaneLength)变为 0:
txtDebug.Text : -280 txtDebug.Text : -279.996 txtDebug.Text : -220.397 txtDebug.Text : -160.79 txtDebug.Text : -101.138 txtDebug.Text : -65.0658 txtDebug.Text : -51.9964 txtDebug.Text : -38.9144 txtDebug.Text : -25.5251 txtDebug.Text : -20.8821 txtDebug.Text : -16.2444 txtDebug.Text : -11.6015 txtDebug.Text : -8.4631 txtDebug.Text : -6.61891 txtDebug.Text : -4.77503 txtDebug.Text : -2.93104 txtDebug.Text : -2.2662 txtDebug.Text : -1.57674 txtDebug.Text : -0.157382 txtDebug.Text : 0
结合 VisualState 中 <VisualTransition From="Closed" To="OpenOverlayLeft"> 节点,
在 0秒到 0:0:0.35 秒时,PaneRoot 由 “隐藏”变为“显示”,并且它的 TranslateX 由 OpenPaneLength
变为 0 :
<VisualTransition From="Closed" To="OpenOverlayLeft"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PaneRoot" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HCPaneBorder" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneTransform" Storyboard.TargetProperty="TranslateX"> <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.NegativeOpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="PaneClipRectangleTransform" Storyboard.TargetProperty="TranslateX"> <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/> <SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0"/> </DoubleAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LightDismissLayer" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualTransition>
2) 添加 C# 中的逻辑,加了注释
#region 从屏幕左侧边缘滑动屏幕时,打开 SplitView 菜单 // SplitView 控件模板中,Pane部分的 Grid Grid PaneRoot; // 引用 SplitView 控件中, 保存从 Pane “关闭” 到“打开”的 VisualTransition // 也就是 <VisualTransition From="Closed" To="OpenOverlayLeft"> 这个 VisualTransition from_ClosedToOpenOverlayLeft_Transition; private void Border_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) { e.Handled = true; // 仅当 SplitView 处于 Overlay 模式时(窗口宽度最小时) if (MySplitView.DisplayMode == SplitViewDisplayMode.Overlay) { if (PaneRoot == null) { // 找到 SplitView 控件中,模板的父容器 Grid grid = Utility.FindVisualChild<Grid>(MySplitView); PaneRoot = grid.FindName("PaneRoot") as Grid; if (from_ClosedToOpenOverlayLeft_Transition == null) { // 获取 SplitView 模板中“视觉状态集合” IList<VisualStateGroup> stateGroup = VisualStateManager.GetVisualStateGroups(grid); // 获取 VisualTransition 对象的集合。 IList<VisualTransition> transitions = stateGroup[0].Transitions; // 找到 SplitView.IsPaneOpen 设置为 true 时,播放的 transition from_ClosedToOpenOverlayLeft_Transition = transitions?.Where(train => train.From == "Closed" && train.To == "OpenOverlayLeft").First(); // 遍历所有 transitions,打印到输出窗口 foreach (var tran in transitions) { Debug.WriteLine("From : " + tran.From + " To : " + tran.To); } } } // 默认为 Collapsed,所以先显示它 PaneRoot.Visibility = Visibility.Visible; // 当在 Border 上向右滑动,并且滑动的总距离需要小于 Panel 的默认宽度。否则会脱离左侧窗口,继续向右拖动 if (e.Cumulative.Translation.X >= 0 && e.Cumulative.Translation.X < MySplitView.OpenPaneLength) { CompositeTransform ct = PaneRoot.RenderTransform as CompositeTransform; ct.TranslateX = (e.Cumulative.Translation.X - MySplitView.OpenPaneLength); } } } private void Border_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) { e.Handled = true; // 仅当 SplitView 处于 Overlay 模式时(窗口宽度最小时) if (MySplitView.DisplayMode == SplitViewDisplayMode.Overlay && PaneRoot != null) { // 因为当 IsPaneOpen 为 true 时,会通过 VisualStateManager 把 PaneRoot.Visibility 设置为 // Visibility.Visible,所以这里把它改为 Visibility.Collapsed,以回到初始状态 PaneRoot.Visibility = Visibility.Collapsed; MySplitView.IsPaneOpen = true; // 因为上面设置 IsPaneOpen = true 会再次播放向右滑动的动画,所以这里使用 SkipToFill() // 方法,直接跳到动画结束状态 from_ClosedToOpenOverlayLeft_Transition?.Storyboard?.SkipToFill(); // 恢复初始状态 CompositeTransform ct = PaneRoot.RenderTransform as CompositeTransform; ct.TranslateX = 0; } } #endregion
MainPage.xaml.cs 页面中,全部的 C# :
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; namespace SwipeableSplitView { public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); } // Debug 数据输出,左侧面板 TranslateX 的变化 private void MySplitView_Loaded(object sender, RoutedEventArgs e) { #if DEBUG Grid grid = Utility.FindVisualChild<Grid>(MySplitView); Binding bind = new Binding(); bind.Path = new PropertyPath("TranslateX"); bind.Source = (grid.FindName("PaneRoot") as Grid).RenderTransform as CompositeTransform; // 显示到 TextBlock 上 txtDebug.SetBinding(TextBlock.TextProperty, bind); txtDebug.RegisterPropertyChangedCallback(TextBlock.TextProperty, (dependencyObject, dependencyProperty) => { // 注册 TextBlock.TextProperty 属性回调事件,显示到输出窗口 Debug.WriteLine("txtDebug.Text : " + txtDebug.Text); }); #endif } #region 从屏幕左侧边缘滑动屏幕时,打开 SplitView 菜单 // SplitView 控件模板中,Pane部分的 Grid Grid PaneRoot; // 引用 SplitView 控件中, 保存从 Pane “关闭” 到“打开”的 VisualTransition // 也就是 <VisualTransition From="Closed" To="OpenOverlayLeft"> 这个 VisualTransition from_ClosedToOpenOverlayLeft_Transition; private void Border_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) { e.Handled = true; // 仅当 SplitView 处于 Overlay 模式时(窗口宽度最小时) if (MySplitView.DisplayMode == SplitViewDisplayMode.Overlay) { if (PaneRoot == null) { // 找到 SplitView 控件中,模板的父容器 Grid grid = Utility.FindVisualChild<Grid>(MySplitView); PaneRoot = grid.FindName("PaneRoot") as Grid; if (from_ClosedToOpenOverlayLeft_Transition == null) { // 获取 SplitView 模板中“视觉状态集合” IList<VisualStateGroup> stateGroup = VisualStateManager.GetVisualStateGroups(grid); // 获取 VisualTransition 对象的集合。 IList<VisualTransition> transitions = stateGroup[0].Transitions; // 找到 SplitView.IsPaneOpen 设置为 true 时,播放的 transition from_ClosedToOpenOverlayLeft_Transition = transitions?.Where(train => train.From == "Closed" && train.To == "OpenOverlayLeft").First(); // 遍历所有 transitions,打印到输出窗口 foreach (var tran in transitions) { Debug.WriteLine("From : " + tran.From + " To : " + tran.To); } } } // 默认为 Collapsed,所以先显示它 PaneRoot.Visibility = Visibility.Visible; // 当在 Border 上向右滑动,并且滑动的总距离需要小于 Panel 的默认宽度。否则会脱离左侧窗口,继续向右拖动 if (e.Cumulative.Translation.X >= 0 && e.Cumulative.Translation.X < MySplitView.OpenPaneLength) { CompositeTransform ct = PaneRoot.RenderTransform as CompositeTransform; ct.TranslateX = (e.Cumulative.Translation.X - MySplitView.OpenPaneLength); } } } private void Border_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) { e.Handled = true; // 仅当 SplitView 处于 Overlay 模式时(窗口宽度最小时) if (MySplitView.DisplayMode == SplitViewDisplayMode.Overlay && PaneRoot != null) { // 因为当 IsPaneOpen 为 true 时,会通过 VisualStateManager 把 PaneRoot.Visibility 设置为 // Visibility.Visible,所以这里把它改为 Visibility.Collapsed,以回到初始状态 PaneRoot.Visibility = Visibility.Collapsed; MySplitView.IsPaneOpen = true; // 因为上面设置 IsPaneOpen = true 会再次播放向右滑动的动画,所以这里使用 SkipToFill() // 方法,直接跳到动画结束状态 from_ClosedToOpenOverlayLeft_Transition?.Storyboard?.SkipToFill(); // 恢复初始状态 CompositeTransform ct = PaneRoot.RenderTransform as CompositeTransform; ct.TranslateX = 0; } } #endregion } }
常用的视图帮助类 Utility:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.UI.Xaml; namespace SwipeableSplitView { /// <summary> /// 视觉状态 工具类 /// </summary> static partial class Utility { public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject { int count = Windows.UI.Xaml.Media.VisualTreeHelper.GetChildrenCount(obj); for (int i = 0; i < count; i++) { DependencyObject child = Windows.UI.Xaml.Media.VisualTreeHelper.GetChild(obj, i); if (child != null && child is T) { return (T)child; } else { T childOfChild = FindVisualChild<T>(child); if (childOfChild != null) return childOfChild; } } return null; } public static VisualStateGroup FindVisualState(FrameworkElement element, string name) { if (element == null || string.IsNullOrWhiteSpace(name)) return null; IList<VisualStateGroup> groups = VisualStateManager.GetVisualStateGroups(element); foreach (var group in groups) { if (group.Name == name) return group; } return null; } } }
完。