Задержка при перетаскивании UIElement в Windows Phone 8.1

Я использую обработчик событий ManipulationDelta для перетаскивания простого эллипса на холсте по экрану. Я использую стандартный подход, опубликованный в Интернете в нескольких местах. Ниже приведен код в моем обработчике событий:

Ellipse dragableItem = sender as Ellipse;
TranslateTransform translateTransform = dragableItem.RenderTransform as TranslateTransform;
double newPosX = Canvas.GetLeft(dragableItem) + translateTransform.X + e.Delta.Translation.X;
double newPosY = Canvas.GetTop(dragableItem) + translateTransform.Y + e.Delta.Translation.Y;

if (!isCanvasBoundary(newPosX, TestCanvas.ActualWidth - dragableItem.ActualWidth, 0))
      translateTransform.X += e.Delta.Translation.X;

if (!isCanvasBoundary(newPosY, TestCanvas.ActualHeight - dragableItem.ActualHeight, 0))
      translateTransform.Y += e.Delta.Translation.Y;

Операция перетаскивания работает нормально, но есть неприятная задержка около 1 секунды между тем, когда пользователь начинает перетаскивание, и тем, когда эллипс фактически меняет свое положение. Я вижу, печатая в отладчике, что сам обработчик событий завершает выполнение почти мгновенно, поэтому я предполагаю, что у него есть что-то, что делает предварительно запрограммированную частоту обновления для всех UIElement на экране, что вызывает эту задержку?

Есть ли что-нибудь вокруг этой проблемы?


person Ali250    schedule 01.03.2015    source источник


Ответы (1)


У меня была такая же проблема некоторое время назад. Я предполагаю, что задержка заключается в том, чтобы решить, является ли жест перетаскиванием или касанием. Трудно коснуться экрана без случайного перетаскивания.

Чтобы устранить эту задержку, вы можете использовать события PointerMove и PointerPressed. Вот мой пример. У вас есть холст с двумя эллипсами, которые можно перетаскивать без задержки.

XAML

<Grid>
    <Canvas x:Name="Board" PointerMoved="Canvas_PointerMoved" Background="Black">
        <Ellipse Width="64" Height="64" Fill="Red"
                 Canvas.Left="32" Canvas.Top="128" PointerPressed="Ellipse_PointerPressed"/>
        <Ellipse Width="96" Height=" 96" Fill="Blue"
                 Canvas.Left="128" Canvas.Top="16" PointerPressed="Ellipse_PointerPressed"/>
    </Canvas>
</Grid>

Как видите, я обрабатываю событие PointerMoved на холсте и событие PointerPressed в эллипсе. Важно, чтобы фон холста не был прозрачным для обработки событий касания.

С#

public sealed partial class MainPage : Page
{
    UIElement draggedItem = null;
    Point offset;

    public MainPage()
    {
        this.InitializeComponent();
        this.NavigationCacheMode = NavigationCacheMode.Required;
    }

    private void Ellipse_PointerPressed(object sender, PointerRoutedEventArgs e)
    {
        draggedItem = sender as UIElement;
        offset = e.GetCurrentPoint(draggedItem).Position;
    }

    private void Canvas_PointerMoved(object sender, PointerRoutedEventArgs e)
    {
        if (draggedItem == null)
            return;

        Point dragPoint = e.GetCurrentPoint(Board).Position;
        Canvas.SetLeft(draggedItem, dragPoint.X - offset.X);
        Canvas.SetTop(draggedItem, dragPoint.Y - offset.Y);
    }
}

Я думаю, что код довольно прост и понятен. Я использую PointerPressed, чтобы решить, какой объект перетаскивается. Я также вычисляю некоторое смещение, потому что мы хотим переместить объект относительно точки, к которой прикасается пользователь.

скриншот

person Łukasz Rejman    schedule 01.03.2015
comment
Спасибо, очень признателен! Одна небольшая проблема заключалась в том, что последний перемещенный эллипс менял положение, даже когда пользователь нажимал на часть холста, где эллипс не расположен. Чтобы исправить это, я добавил событие PointerReleased и простую логическую переменную, которая устанавливает значение true в PointerPressed и обратно в false в PointerReleased. Затем в PointerMoved я проверял логическое значение и перемещал эллипс только в том случае, если это было правдой. Кроме того, я обнаружил, что печать в отладчике чего-либо из события PointerMoved приводит к существенной задержке. - person Ali250; 02.03.2015
comment
@ Ali250 Ali250 Более простой способ, который я нашел, - это установить draggedItem = null; в событии PointerReleased, а не настраивать новую логическую переменную. - person Stu Ayton; 21.06.2015
comment
отличное альтернативное решение +1. - person hushyon; 02.11.2016