我有以下代码:
private Point initialpoint;
private void ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
initialpoint = e.Position;
}
private void ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
Point currentpoint = e.Position;
if (currentpoint.X - initialpoint.X >= 100)
{
System.Diagnostics.Debug.WriteLine("Swipe Right");
e.Complete();
}
}
我可以非常轻松地处理1个手指轻扫手势,但我还想处理2,3,4个手指滑动手势。谁能告诉我怎么做?
答案 0 :(得分:12)
根据此MSDN Forum Posting,您需要使用pointer通知。包含工作示例代码的文档位于MSDN Library
中从上一个链接:
指针对象代表一个唯一的输入" contact"来自输入设备(例如鼠标,笔/手写笔,单指或多指)的(PointerPoint)。系统在首次检测到接触时创建指针,并在指针离开(离开)检测范围或被取消时销毁它。在多个设备或多点触摸输入的情况下,每个联系人都被视为唯一指针。
只是一个警告,我没有多点触控Windows 8设备来测试此代码。因此它已经在Simuator中进行了测试,具有所有限制,并且如上面提到的链接,Windows 8没有内置手势支持来检测多个手指,您必须使用较低级别的功能。
首先,我在上面的MSDN示例代码中添加了两个字典,并为您的Swipe Threshold添加了两个变量到类定义。
Dictionary<uint, Point> startLocation;
Dictionary<uint, bool> pointSwiped;
int swipeThresholdX = 100;
int swipeThresholdY = 100;
然后我在Form&#39的构造函数中初始化Dictionarys
startLocation = new Dictionary<uint, Point>((int)SupportedContacts.Contacts);
pointSwiped = new Dictionary<uint, bool>((int)SupportedContacts.Contacts);
然后,每个添加原始字典或删除了一个项目的地方我都对新词典做了同样的事情
中加入:
startLocation[pt.PointerId] = pt.Position;
pointSwiped[pt.PointerId] = false;
去除:
startLocation.Remove(pt.PointerId);
pointSwiped.Remove(pt.PointerId);
然后最终将它们放在PointerMovedEvent:
中private void targetContainer_PointerMoved(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
if (currentPoint.IsInContact)
{
if (startLocation.ContainsKey(currentPoint.PointerId))
{
Point startPoint = startLocation[currentPoint.PointerId];
if (Math.Abs(currentPoint.Position.X - startPoint.X) > swipeThresholdX) // I only did one Axis for testing
{
pointSwiped[currentPoint.PointerId] = true;
}
}
}
updateInfoPop(e);
}
最终修改的MSDN示例:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
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;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace PointerInput
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
Windows.Devices.Input.TouchCapabilities SupportedContacts = new Windows.Devices.Input.TouchCapabilities();
uint numActiveContacts;
Dictionary<uint, Windows.UI.Input.PointerPoint> contacts;
Dictionary<uint, Point> startLocation;
Dictionary<uint, bool> pointSwiped;
int swipeThresholdX = 100;
int swipeThresholdY = 100;
public MainPage()
{
this.InitializeComponent();
numActiveContacts = 0;
contacts = new Dictionary<uint, Windows.UI.Input.PointerPoint>((int)SupportedContacts.Contacts);
startLocation = new Dictionary<uint, Point>((int)SupportedContacts.Contacts);
pointSwiped = new Dictionary<uint, bool>((int)SupportedContacts.Contacts);
targetContainer.PointerPressed += new PointerEventHandler(targetContainer_PointerPressed);
targetContainer.PointerEntered += new PointerEventHandler(targetContainer_PointerEntered);
targetContainer.PointerReleased += new PointerEventHandler(targetContainer_PointerReleased);
targetContainer.PointerExited += new PointerEventHandler(targetContainer_PointerExited);
targetContainer.PointerCanceled += new PointerEventHandler(targetContainer_PointerCanceled);
targetContainer.PointerCaptureLost += new PointerEventHandler(targetContainer_PointerCaptureLost);
targetContainer.PointerMoved += new PointerEventHandler(targetContainer_PointerMoved);
}
// PointerPressed and PointerReleased events do not always occur in pairs.
// Your app should listen for and handle any event that might conclude a pointer down action
// (such as PointerExited, PointerCanceled, and PointerCaptureLost).
void targetContainer_PointerPressed(object sender, PointerRoutedEventArgs e)
{
if (Convert.ToBoolean(SupportedContacts.TouchPresent) && (numActiveContacts > SupportedContacts.Contacts))
{
// cannot support more contacts
eventLog.Text += "\nNumber of contacts exceeds the number supported by the device.";
return;
}
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);
// Update event sequence.
eventLog.Text += "\nDown: " + pt.PointerId;
// Change background color of target when pointer contact detected.
targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Green);
// Check if pointer already exists (if enter occurred prior to down).
if (contacts.ContainsKey(pt.PointerId))
{
return;
}
contacts[pt.PointerId] = pt;
startLocation[pt.PointerId] = pt.Position;
pointSwiped[pt.PointerId] = false;
++numActiveContacts;
e.Handled = true;
// Display pointer details.
createInfoPop(e);
}
private void targetContainer_PointerEntered(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);
// Update event sequence.
eventLog.Text += "\nOver: " + pt.PointerId;
if (contacts.Count == 0)
{
// Change background color of target when pointer contact detected.
targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Blue);
}
// Check if pointer already exists (if enter occurred prior to down).
if (contacts.ContainsKey(pt.PointerId))
{
return;
}
// Push new pointer Id onto expando target pointers array.
contacts[pt.PointerId] = pt;
startLocation[pt.PointerId] = pt.Position;
pointSwiped[pt.PointerId] = false;
++numActiveContacts;
e.Handled = true;
// Display pointer details.
createInfoPop(e);
}
// Fires for for various reasons, including:
// - User interactions
// - Programmatic caputre of another pointer
// - Captured pointer was deliberately released
// PointerCaptureLost can fire instead of PointerReleased.
private void targetContainer_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);
// Update event sequence.
eventLog.Text += "\nPointer capture lost: " + pt.PointerId;
if (contacts.ContainsKey(pt.PointerId))
{
checkSwipe();
contacts[pt.PointerId] = null;
contacts.Remove(pt.PointerId);
startLocation.Remove(pt.PointerId);
if (pointSwiped.ContainsKey(pt.PointerId))
pointSwiped.Remove(pt.PointerId);
--numActiveContacts;
}
// Update the UI and pointer details.
foreach (TextBlock tb in pointerInfo.Children)
{
if (tb.Name == e.Pointer.PointerId.ToString())
{
pointerInfo.Children.Remove(tb);
}
}
if (contacts.Count == 0)
{
targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
}
e.Handled = true;
}
// Fires for for various reasons, including:
// - A touch contact is canceled by a pen coming into range of the surface.
// - The device doesn't report an active contact for more than 100ms.
// - The desktop is locked or the user logged off.
// - The number of simultaneous contacts exceeded the number supported by the device.
private void targetContainer_PointerCanceled(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);
// Update event sequence.
eventLog.Text += "\nPointer canceled: " + pt.PointerId;
if (contacts.ContainsKey(pt.PointerId))
{
checkSwipe();
contacts[pt.PointerId] = null;
contacts.Remove(pt.PointerId);
startLocation.Remove(pt.PointerId);
if (pointSwiped.ContainsKey(pt.PointerId))
pointSwiped.Remove(pt.PointerId);
--numActiveContacts;
}
// Update the UI and pointer details.
foreach (TextBlock tb in pointerInfo.Children)
{
if (tb.Name == e.Pointer.PointerId.ToString())
{
pointerInfo.Children.Remove(tb);
}
}
if (contacts.Count == 0)
{
targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
}
e.Handled = true;
}
private void targetContainer_PointerExited(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);
// Update event sequence.
eventLog.Text += "\nPointer exited: " + pt.PointerId;
if (contacts.ContainsKey(pt.PointerId))
{
checkSwipe();
contacts[pt.PointerId] = null;
contacts.Remove(pt.PointerId);
startLocation.Remove(pt.PointerId);
if (pointSwiped.ContainsKey(pt.PointerId))
pointSwiped.Remove(pt.PointerId);
--numActiveContacts;
}
// Update the UI and pointer details.
foreach (TextBlock tb in pointerInfo.Children)
{
if (tb.Name == e.Pointer.PointerId.ToString())
{
pointerInfo.Children.Remove(tb);
}
}
if (contacts.Count == 0)
{
targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Gray);
}
e.Handled = true;
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
void targetContainer_PointerReleased(object sender, PointerRoutedEventArgs e)
{
foreach (TextBlock tb in pointerInfo.Children)
{
if (tb.Name == e.Pointer.PointerId.ToString())
{
pointerInfo.Children.Remove(tb);
}
}
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);
// Update event sequence.
eventLog.Text += "\nUp: " + pt.PointerId;
// Change background color of target when pointer contact detected.
targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Red);
if (contacts.ContainsKey(pt.PointerId))
{
checkSwipe();
contacts[pt.PointerId] = null;
contacts.Remove(pt.PointerId);
startLocation.Remove(pt.PointerId);
if(pointSwiped.ContainsKey(pt.PointerId))
pointSwiped.Remove(pt.PointerId);
--numActiveContacts;
}
e.Handled = true;
}
private void targetContainer_PointerMoved(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
if (currentPoint.IsInContact)
{
if (startLocation.ContainsKey(currentPoint.PointerId))
{
Point startPoint = startLocation[currentPoint.PointerId];
if (Math.Abs(currentPoint.Position.X - startPoint.X) > swipeThresholdX) // I only did one Axis for testing
{
pointSwiped[currentPoint.PointerId] = true;
}
}
}
updateInfoPop(e);
}
int numberOfSwipedFingers()
{
int count = 0;
foreach (var item in pointSwiped)
{
if (item.Value) { count += 1; }
}
return count;
}
void checkSwipe()
{
int fingers = numberOfSwipedFingers();
if (fingers > 1)
{
eventLog.Text += "\nNumber of Swiped fingers = " + fingers;
}
else if (fingers == 1)
{
eventLog.Text += "\nNumber of Swiped fingers = " + fingers;
}
if(fingers > 0)
pointSwiped.Clear();
}
void createInfoPop(PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
TextBlock pointerDetails = new TextBlock();
pointerDetails.Name = currentPoint.PointerId.ToString();
pointerDetails.Foreground = new SolidColorBrush(Windows.UI.Colors.White);
pointerInfo.Children.Add(pointerDetails);
pointerDetails.Text = queryPointer(e);
}
void updateInfoPop(PointerRoutedEventArgs e)
{
foreach (TextBlock pointerDetails in pointerInfo.Children)
{
if (pointerDetails.Name == e.Pointer.PointerId.ToString())
{
pointerDetails.Text = queryPointer(e);
}
}
}
String queryPointer(PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
String details = "";
switch (e.Pointer.PointerDeviceType)
{
case Windows.Devices.Input.PointerDeviceType.Mouse:
details += "\nPointer type: mouse";
break;
case Windows.Devices.Input.PointerDeviceType.Pen:
details += "\nPointer type: pen";
if (e.Pointer.IsInContact)
{
details += "\nPressure: " + currentPoint.Properties.Pressure;
details += "\nrotation: " + currentPoint.Properties.Orientation;
details += "\nTilt X: " + currentPoint.Properties.XTilt;
details += "\nTilt Y: " + currentPoint.Properties.YTilt;
details += "\nBarrel button pressed: " + currentPoint.Properties.IsBarrelButtonPressed;
}
break;
case Windows.Devices.Input.PointerDeviceType.Touch:
details += "\nPointer type: touch";
details += "\nrotation: " + currentPoint.Properties.Orientation;
details += "\nTilt X: " + currentPoint.Properties.XTilt;
details += "\nTilt Y: " + currentPoint.Properties.YTilt;
break;
default:
details += "\nPointer type: n/a";
break;
}
GeneralTransform gt = targetContainer.TransformToVisual(page);
Point screenPoint;
screenPoint = gt.TransformPoint(new Point(currentPoint.Position.X, currentPoint.Position.Y));
details += "\nPointer Id: " + currentPoint.PointerId.ToString() +
"\nPointer location (parent): " + currentPoint.Position.X + ", " + currentPoint.Position.Y +
"\nPointer location (screen): " + screenPoint.X + ", " + screenPoint.Y;
return details;
}
}
}
答案 1 :(得分:1)
我将Mark Hall的答案改编成了一个单独的课程,并处理向上,向下,向左和向右滑动。它仍有问题,你可以在不同的时间举起手指,并获得多个事件,并可以改进,虽然它适合我的需要:
public enum DirectionSwiped
{
None,
Up,
Down,
Left,
Right
}
public class SwipeEventArgs : EventArgs
{
public DirectionSwiped Direction { get; set; }
public int NumberOfTouches { get; set; }
}
public class SwipeGestureDetector
{
public EventHandler<SwipeEventArgs> SwipeDetected;
// How much of the grid needs to be covered by the swipe?
private const double SWIPE_THRESHOLD = 0.5;
// How much drift is allowed in the opposite axis?
private const int ALLOWED_DRIFT = 100;
Windows.Devices.Input.TouchCapabilities SupportedContacts = new Windows.Devices.Input.TouchCapabilities();
uint numActiveContacts;
Dictionary<uint, Windows.UI.Input.PointerPoint> contacts;
Dictionary<uint, Point> startLocation;
Dictionary<uint, DirectionSwiped> pointSwiped;
private Grid mGrid;
public SwipeGestureDetector(Grid grid)
{
mGrid = grid;
numActiveContacts = 0;
contacts = new Dictionary<uint, Windows.UI.Input.PointerPoint>((int)SupportedContacts.Contacts);
startLocation = new Dictionary<uint, Point>((int)SupportedContacts.Contacts);
pointSwiped = new Dictionary<uint, DirectionSwiped>((int)SupportedContacts.Contacts);
grid.PointerPressed += new PointerEventHandler(Grid_PointerPressed);
grid.PointerEntered += new PointerEventHandler(Grid_PointerEntered);
grid.PointerReleased += new PointerEventHandler(Grid_PointerReleased);
grid.PointerExited += new PointerEventHandler(Grid_PointerExited);
grid.PointerCanceled += new PointerEventHandler(Grid_PointerCanceled);
grid.PointerCaptureLost += new PointerEventHandler(Grid_PointerCaptureLost);
grid.PointerMoved += new PointerEventHandler(Grid_PointerMoved);
}
// PointerPressed and PointerReleased events do not always occur in pairs.
// Your app should listen for and handle any event that might conclude a pointer down action
// (such as PointerExited, PointerCanceled, and PointerCaptureLost).
void Grid_PointerPressed(object sender, PointerRoutedEventArgs e)
{
if (Convert.ToBoolean(SupportedContacts.TouchPresent) && (numActiveContacts > SupportedContacts.Contacts))
{
// cannot support more contacts
Debug.WriteLine("\nNumber of contacts exceeds the number supported by the device.");
return;
}
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);
// Check if pointer already exists (if enter occurred prior to down).
if (contacts.ContainsKey(pt.PointerId))
{
return;
}
contacts[pt.PointerId] = pt;
startLocation[pt.PointerId] = pt.Position;
pointSwiped[pt.PointerId] = DirectionSwiped.None;
++numActiveContacts;
e.Handled = true;
}
private void Grid_PointerEntered(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);
// Check if pointer already exists (if enter occurred prior to down).
if (contacts.ContainsKey(pt.PointerId))
{
return;
}
// Push new pointer Id onto expando target pointers array.
contacts[pt.PointerId] = pt;
startLocation[pt.PointerId] = pt.Position;
pointSwiped[pt.PointerId] = DirectionSwiped.None;
++numActiveContacts;
e.Handled = true;
}
// Fires for for various reasons, including:
// - User interactions
// - Programmatic caputre of another pointer
// - Captured pointer was deliberately released
// PointerCaptureLost can fire instead of PointerReleased.
private void Grid_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);
if (contacts.ContainsKey(pt.PointerId))
{
checkSwipe();
contacts[pt.PointerId] = null;
contacts.Remove(pt.PointerId);
startLocation.Remove(pt.PointerId);
if (pointSwiped.ContainsKey(pt.PointerId))
pointSwiped.Remove(pt.PointerId);
--numActiveContacts;
}
e.Handled = true;
}
// Fires for for various reasons, including:
// - A touch contact is canceled by a pen coming into range of the surface.
// - The device doesn't report an active contact for more than 100ms.
// - The desktop is locked or the user logged off.
// - The number of simultaneous contacts exceeded the number supported by the device.
private void Grid_PointerCanceled(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);
if (contacts.ContainsKey(pt.PointerId))
{
checkSwipe();
contacts[pt.PointerId] = null;
contacts.Remove(pt.PointerId);
startLocation.Remove(pt.PointerId);
if (pointSwiped.ContainsKey(pt.PointerId))
pointSwiped.Remove(pt.PointerId);
--numActiveContacts;
}
e.Handled = true;
}
private void Grid_PointerExited(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);
if (contacts.ContainsKey(pt.PointerId))
{
checkSwipe();
contacts[pt.PointerId] = null;
contacts.Remove(pt.PointerId);
startLocation.Remove(pt.PointerId);
if (pointSwiped.ContainsKey(pt.PointerId))
pointSwiped.Remove(pt.PointerId);
--numActiveContacts;
}
e.Handled = true;
}
void Grid_PointerReleased(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);
if (contacts.ContainsKey(pt.PointerId))
{
checkSwipe();
contacts[pt.PointerId] = null;
contacts.Remove(pt.PointerId);
startLocation.Remove(pt.PointerId);
if (pointSwiped.ContainsKey(pt.PointerId))
pointSwiped.Remove(pt.PointerId);
--numActiveContacts;
}
e.Handled = true;
}
private void Grid_PointerMoved(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(mGrid);
if (currentPoint.IsInContact)
{
if (startLocation.ContainsKey(currentPoint.PointerId))
{
Point startPoint = startLocation[currentPoint.PointerId];
// Compare startPoint to current location and determine if that point did a swipe?
double horizontalMovement = currentPoint.Position.X - startPoint.X;
double verticalMovement = currentPoint.Position.Y - startPoint.Y;
double horizontalDistance = Math.Abs(horizontalMovement);
double verticalDistance = Math.Abs(verticalMovement);
double requiredLeftMovement = mGrid.ActualWidth * SWIPE_THRESHOLD * -1;
double requiredRightMovement = mGrid.ActualWidth * SWIPE_THRESHOLD;
double requiredUpMovement = mGrid.ActualHeight * SWIPE_THRESHOLD * -1;
double requiredDownMovement = mGrid.ActualHeight * SWIPE_THRESHOLD;
if (verticalMovement < requiredUpMovement && horizontalDistance < 100)
{
pointSwiped[currentPoint.PointerId] = DirectionSwiped.Up;
}
else if (verticalMovement > requiredDownMovement && horizontalDistance < ALLOWED_DRIFT)
{
pointSwiped[currentPoint.PointerId] = DirectionSwiped.Down;
}
else if (horizontalMovement > requiredRightMovement && verticalDistance < ALLOWED_DRIFT)
{
pointSwiped[currentPoint.PointerId] = DirectionSwiped.Right;
}
else if (horizontalMovement < requiredLeftMovement && verticalDistance < ALLOWED_DRIFT)
{
pointSwiped[currentPoint.PointerId] = DirectionSwiped.Left;
}
}
}
}
void checkSwipe()
{
NotififyListenerIfSwiped(DirectionSwiped.Up);
NotififyListenerIfSwiped(DirectionSwiped.Down);
NotififyListenerIfSwiped(DirectionSwiped.Left);
NotififyListenerIfSwiped(DirectionSwiped.Right);
}
private void NotififyListenerIfSwiped(DirectionSwiped direction)
{
int fingers = numberOfSwipedFingers(direction);
if (fingers >= 1)
{
if (SwipeDetected != null)
{
SwipeDetected(this, new SwipeEventArgs() { Direction = direction, NumberOfTouches = fingers });
}
}
if (fingers > 0)
pointSwiped.Clear();
}
int numberOfSwipedFingers(DirectionSwiped direction)
{
int count = 0;
foreach (var item in pointSwiped)
{
DirectionSwiped swipe = item.Value;
if (swipe == direction)
{
count += 1;
}
}
return count;
}
}
用法
public void Gesture_Detected(Object sender, SwipeEventArgs e)
{
Debug.WriteLine("Number of touches: " + e.NumberOfTouches + " Direction: " + e.Direction);
}
public MainPage()
{
this.InitializeComponent();
SwipeGestureDetector gestureDetector = new SwipeGestureDetector(this.rootGrid);
gestureDetector.SwipeDetected += Gesture_Detected;