Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion GestureDemo/Presentation/ShellViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ public MenuItem SelectedMenuItem
if (Set(ref this.selectedMenuItem, value)) {
OnPropertyChanged("SelectedPageType");

// auto-close split view pane
// This will handle most cases where the SplitView pane needs to close.
// There are other special cases where we may need to manually close the SplitView Pane.
// For example, selecting the same menu item will not set this property—therefore, we need
// to manually close the Pane in that case.
this.IsSplitViewPaneOpen = false;
}
}
Expand Down
2 changes: 1 addition & 1 deletion GestureDemo/Shell.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="LayoutRoot" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Border x:Name="LayoutRoot" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" PointerReleased="OnLayoutRootPointerReleased">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
Expand Down
8 changes: 8 additions & 0 deletions GestureDemo/Shell.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,13 @@ public Frame RootFrame
return this.Frame;
}
}

private void OnLayoutRootPointerReleased(object sender, PointerRoutedEventArgs e)
{
// When the currently selected menu item is selected again, we should close the SplitView pane.
// Normally, the Pane is closed in the ViewModel.SelectedMenuItem setter but because
// the SelectedMenuItem is selected again, the setter is not called.
this.SplitView.IsSwipeablePaneOpen = false;
}
}
}
91 changes: 53 additions & 38 deletions GestureDemo/SwipeableSplitView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -336,64 +336,79 @@ void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)

async void OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
var x = e.Velocities.Linear.X;

// ignore a little bit velocity (+/-0.1)
if (x <= -0.1)
{
CloseSwipeablePane();
}
else if (x > -0.1 && x < 0.1)
// First, determine if the swipe was horizontal or vertical. Horizontal swipes should open or
// close the SwipeablePane. A vertical swipe should manipulate the PanSelector.
var horizontalSwipe = Math.Abs(e.Cumulative.Translation.X) > Math.Abs(e.Cumulative.Translation.Y);
if (horizontalSwipe)
{
if (Math.Abs(_panAreaTransform.TranslateX) > Math.Abs(PanAreaInitialTranslateX) / 2)
var horizontalVelocity = e.Velocities.Linear.X;

// Ignore a little bit velocity (+/-0.1).
if (horizontalVelocity <= -0.1)
{
CloseSwipeablePane();
}
else if (horizontalVelocity > -0.1 && horizontalVelocity < 0.1)
{
if (Math.Abs(_panAreaTransform.TranslateX) > Math.Abs(PanAreaInitialTranslateX) / 2)
{
CloseSwipeablePane();
}
else
{
OpenSwipeablePane();
}
}
else
{
OpenSwipeablePane();
}

// In case the ManipulationDelta highlighted a menuItem, remove the highlight.
var itemContainer = _menuItems[_toBeSelectedIndex];
VisualStateManager.GoToState(itemContainer, "Normal", true);
}
else
{
OpenSwipeablePane();
}

if (this.IsPanSelectorEnabled)
{
if (sender == _paneRoot)
if (this.IsPanSelectorEnabled)
{
// if it's a flick, meaning the user wants to cancel the action, so we remove all the highlights;
// or it's intended to be a horizontal gesture, we also remove all the highlights
if (Math.Abs(e.Velocities.Linear.Y) >= 2 ||
Math.Abs(e.Cumulative.Translation.X) > Math.Abs(e.Cumulative.Translation.Y))
if (sender == _paneRoot)
{
// If it's a flick, meaning the user wants to cancel the action, so we remove all the highlights;
// or it's intended to be a horizontal gesture, we also remove all the highlights.
if (Math.Abs(e.Velocities.Linear.Y) >= 2)
{
foreach (var item in _menuItems)
{
VisualStateManager.GoToState(item, "Normal", true);
}

return;
}

// Un-highlight everything first.
foreach (var item in _menuItems)
{
VisualStateManager.GoToState(item, "Normal", true);
VisualStateManager.GoToState(item, "Unselected", true);
}

return;
}
// Highlight the item that's going to be selected.
var itemContainer = _menuItems[_toBeSelectedIndex];
VisualStateManager.GoToState(itemContainer, "Selected", true);

// Do a selection after a short delay to allow visual effect takes place first.
await Task.Delay(250);
_menuHost.SelectedIndex = _toBeSelectedIndex;

// un-highlight everything first
foreach (var item in _menuItems)
// Make sure the Pane is closed. This must be called in case the user
// selects the previously selected Menu item.
CloseSwipeablePane();
}
else
{
VisualStateManager.GoToState(item, "Unselected", true);
// Recalculate the starting distance.
_startingDistance = _distancePerItem * _menuHost.SelectedIndex;
}

// highlight the item that's going to be selected
var itemContainer = _menuItems[_toBeSelectedIndex];
VisualStateManager.GoToState(itemContainer, "Selected", true);

// do a selection after a short delay to allow visual effect takes place first
await Task.Delay(250);
_menuHost.SelectedIndex = _toBeSelectedIndex;
}
else
{
// recalculate the starting distance
_startingDistance = _distancePerItem * _menuHost.SelectedIndex;
}
}
}
Expand Down