昨天想在 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 <Grid389 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>
View Code
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" ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ="http://schemas.microsoft.com/winfx/2006/xaml" ="using:SwipeableSplitView" ="http://schemas.microsoft.com/expression/blend/2008" ="http://schemas.open 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>
View Code
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 : -280txtDebug.Text : -279.996txtDebug.Text : -220.397txtDebug.Text : -160.79txtDebug.Text : -101.138txtDebug.Text : -65.0658txtDebug.Text : -51.9964txtDebug.Text : -38.9144txtDebug.Text : -25.5251txtDebug.Text : -20.8821txtDebug.Text : -16.2444txtDebug.Text : -11.6015txtDebug.Text : -8.4631txtDebug.Text : -6.61891txtDebug.Text : -4.77503txtDebug.Text : -2.93104txtDebug.Text : -2.2662txtDebug.Text : -1.57674txtDebug.Text : -0.157382txtDebug.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>
View Code
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 }}
View Code
常用的视图帮助类 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; } }}
View Code
完。
SwipeableSplitView工程代码下载
原标题:10、Windows10 上,在窗口左侧向右滑动打开 SplitView 的 Pane面板
关键词:Windows