Забавяне при плъзгане/пускане на 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 секунда между момента, в който потребителят започне да плъзга, до момента, в който елипсата действително промени позицията си. Мога да видя, като отпечатам в Debugger, че самият манипулатор на събития завършва изпълнението почти мигновено, така че предполагам, че има нещо, което да направи предварително програмирана честота на опресняване за всички UIElements на екрана, което причинява това забавяне?

Има ли все пак около този проблем?


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 събитие в canvas и PointerPressed събитие в елипси. Важно е фонът на платното да не е прозрачен, за да се справят със събитията при докосване.

C#

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 и проста променлива bool, която го настройва на true в PointerPressed и обратно на false в PointerReleased. Тогава в PointerMoved щях да проверя bool и да преместя елипсата само ако е вярно. Освен това открих, че отпечатването на каквото и да било в Debugger от събитието PointerMoved въвежда значително забавяне. - person Ali250; 02.03.2015
comment
@Ali250 Един по-лесен начин, който намерих, беше да задам draggedItem = null; в събитието PointerReleased, вместо да настройвам нова променлива bool - person Stu Ayton; 21.06.2015
comment
страхотно алтернативно решение +1. - person hushyon; 02.11.2016