Захват двойного касания на мультисенсорном экране - PullRequest
5 голосов
/ 25 января 2012

Я опубликовал еще один вопрос о том, как «вручную» захватить двойное касание, отслеживая промежуток времени между касаниями события TouchDown, но он довольно глючный.Кто-нибудь знает о стандартном способе / событии Microsoft по захвату двойного касания на мультитач-экране?

Большое спасибо,

Дан

Ответы [ 4 ]

10 голосов
/ 16 октября 2012

Я проверяю комбинацию местоположения крана и секундомера, и она отлично работает!

private readonly Stopwatch _doubleTapStopwatch = new Stopwatch();
private Point _lastTapLocation;

public event EventHandler DoubleTouchDown;

protected virtual void OnDoubleTouchDown()
{
    if (DoubleTouchDown != null)
        DoubleTouchDown(this, EventArgs.Empty);
}

private bool IsDoubleTap(TouchEventArgs e)
{
    Point currentTapPosition = e.GetTouchPoint(this).Position;
    bool tapsAreCloseInDistance = currentTapPosition.GetDistanceTo(_lastTapLocation) < 40;
    _lastTapLocation = currentTapPosition;

    TimeSpan elapsed = _doubleTapStopwatch.Elapsed;
    _doubleTapStopwatch.Restart();
    bool tapsAreCloseInTime = (elapsed != TimeSpan.Zero && elapsed < TimeSpan.FromSeconds(0.7));

    return tapsAreCloseInDistance && tapsAreCloseInTime;
}

private void OnPreviewTouchDown(object sender, TouchEventArgs e)
{
    if (IsDoubleTap(e))
        OnDoubleTouchDown();
}

В PreviewTouchDown проверяется, является ли это DoubleTap.

3 голосов
/ 13 апреля 2015

Ответ Jowens мне очень помог (если бы моя репутация позволяла мне, я бы проголосовал за нее;)) НО мне пришлось настроить его, чтобы он работал только с двойными нажатиями. В исходном коде любой касание выше 2 считается двойным касанием. Помогло изменение _lastTapLocation на обнуляемое значение и сброс его, когда двойное касание помогло.

private Point? _lastTapLocation;

private bool IsDoubleTap(TouchEventArgs e)
    {
        Point currentTapPosition = e.GetTouchPoint(this).Position;
        bool tapsAreCloseInDistance = false;
        if (_lastTapLocation != null)
        {
            tapsAreCloseInDistance = GetDistanceBetweenPoints(currentTapPosition, (Point)_lastTapLocation) < 70;
        }
        _lastTapLocation = currentTapPosition;

        TimeSpan elapsed = _doubleTapStopwatch.Elapsed;
        _doubleTapStopwatch.Restart();
        bool tapsAreCloseInTime = (elapsed != TimeSpan.Zero && elapsed < TimeSpan.FromSeconds(0.7));

        if (tapsAreCloseInTime && tapsAreCloseInDistance)
        {
            _lastTapLocation = null;
        }
        return tapsAreCloseInDistance && tapsAreCloseInTime;
    }
1 голос
/ 19 августа 2016

Добавляя к ответу Андреаса, Вы также можете удалить код, связанный с секундомером.

StylusSystemGestureEventArgs также имеет свойство Timestamp , котороеЯ считаю, что подсчитывает в миллисекундах.

Таким образом, вместо использования секундомера для вычисления из TimeSpan, добавьте поле int _lastTimestamp и вычтите метки времени.

public static class ext
{
    private static Point? _lastTapLocation;

    // Stopwatch changed to int
    private int _lastTimestamp = 0;

    public static bool IsDoubleTap(this StylusSystemGestureEventArgs e, IInputElement iInputElement)
    {
        Point currentTapPosition = e.GetPosition(iInputElement);
        bool tapsAreCloseInDistance = false;
        if (_lastTapLocation != null)
        {
            tapsAreCloseInDistance = GetDistanceBetweenPoints(currentTapPosition, (Point)_lastTapLocation) < 70;
        }
        _lastTapLocation = currentTapPosition;

        // This replaces the previous TimeSpan calculation
        bool tapsAreCloseInTime = ((e.Timestamp - _lastTimestamp) < 700);

        if (tapsAreCloseInTime && tapsAreCloseInDistance)
        {
            _lastTapLocation = null;
        }

        _lastTimestamp = e.Timestamp;

        return tapsAreCloseInDistance && tapsAreCloseInTime;
    }
}
1 голос
/ 09 июня 2016

Я думаю, что использование события StylusSystemGesture более уместно. Вот мой код.

    public static class ext
{
private static Point? _lastTapLocation;
        private static readonly Stopwatch _DoubleTapStopwatch = new Stopwatch();
        public static bool IsDoubleTap(this StylusSystemGestureEventArgs e, IInputElement iInputElement)
        {
            Point currentTapPosition = e.GetPosition(iInputElement);
            bool tapsAreCloseInDistance = false;
            if (_lastTapLocation != null)
            {
                tapsAreCloseInDistance = GetDistanceBetweenPoints(currentTapPosition, (Point)_lastTapLocation) < 70;
            }
            _lastTapLocation = currentTapPosition;

            TimeSpan elapsed = _DoubleTapStopwatch.Elapsed;
            _DoubleTapStopwatch.Restart();
            bool tapsAreCloseInTime = (elapsed != TimeSpan.Zero && elapsed < TimeSpan.FromSeconds(0.7));

            if (tapsAreCloseInTime && tapsAreCloseInDistance)
            {
                _lastTapLocation = null;
            }
            return tapsAreCloseInDistance && tapsAreCloseInTime;
        }
}

Использование:

 private void UIElement_OnStylusSystemGesture(object sender, StylusSystemGestureEventArgs e)
    {
        if (e.SystemGesture == SystemGesture.Tap)
        {
            if (e.IsDoubleTap(sender as IInputElement))
            {
               // Do your stuff here
            }
        }
    }
...