简体   繁体   English

如何使我的Rectangle对触摸事件做出反应,就像对鼠标/指针事件一样?

[英]How can I make my Rectangle react to touch events like it does for mouse/pointer events?

On my MainPage, I have a Stackpanel full of multicolored Rectangles, and they all start with Margin set to (0,5,0,5). 在我的MainPage上,我有一个充满彩色矩形的Stackpanel,它们都以Margin设置为(0,5,0,5)开头。 I would like to allow the user to move these rectangles horizontally only. 我想允许用户仅水平移动这些矩形。 Since Rectangles do not have Mouse events, I use the Pointer to achieve this. 由于矩形没有鼠标事件,因此我使用了指针来实现这一点。 The flow is: user taps on a Rectangle to select it, cursor changes to give user visual cue, user drags Rectangle left or right. 流程是:用户点击一个Rectangle来选择它,更改光标以提供视觉提示,用户向左或向右拖动Rectangle。 (Note that the Stackpanel does have a vertical scrollviewer, if that matters). (请注意,Stackpanel确实有一个垂直滚动查看器)。 Here is my C# code: 这是我的C#代码:

private void Rectangle_FirstClick(object sender, EventArgs e)
{
    // Give rectangle a white border to imply selection
    Rectangle myControl = sender as Rectangle;
    myControl.StrokeThickness = 1;
    myControl.Stroke = new SolidColorBrush(Color.FromArgb(255, 240, 240, 240));

    // Provide visual cue to mouse users by changing the pointer immediately
    Window.Current.CoreWindow.PointerCursor = new Windows.UI.Core.CoreCursor(Windows.UI.Core.CoreCursorType.SizeWestEast, 0);

    // Handle mouse leaving/re-entering the track piece
    myControl.PointerEntered += MyControl_PointerEntered;
    myControl.PointerExited += MyControl_PointerExited;

    // Handle the drag event
    myControl.PointerPressed += MyControl_PointerPressed;
    myControl.PointerReleased += MyControl_PointerReleased;
    myControl.PointerMoved += MyControl_PointerMoved;
}

Here are the individual event handlers 以下是各个事件处理程序

bool PossibleDragStart = false;
Point InitialDragPoint = new Point(0, 0);

private void MyControl_PointerExited(object sender, PointerRoutedEventArgs e)
{
    Window.Current.CoreWindow.PointerCursor = new Windows.UI.Core.CoreCursor(Windows.UI.Core.CoreCursorType.Arrow, 0);
}

private void MyControl_PointerEntered(object sender, PointerRoutedEventArgs e)
{
    Window.Current.CoreWindow.PointerCursor = new Windows.UI.Core.CoreCursor(Windows.UI.Core.CoreCursorType.SizeWestEast, 0);
}

private void MyControl_PointerPressed(object sender, PointerRoutedEventArgs e)
{
    PossibleDragStart = true;
    InitialDragPoint = e.GetCurrentPoint(sender as Rectangle).Position;
}

private void MyControl_PointerReleased(object sender, PointerRoutedEventArgs e)
{
    PossibleDragStart = false;
}

private void MyControl_PointerMoved(object sender, PointerRoutedEventArgs e)
{
    // If pointer pressed without release, and then moved, we are dragging
    if (PossibleDragStart)
    {
        Point CurrentDragPoint = e.GetCurrentPoint(AudioTracksRightContainer).Position;
        StatusBar.Text = CurrentDragPoint.X.ToString();

        // Calculate drag offset by subtracting Current Position from Initial Position
        double SegmentMargin = CurrentDragPoint.X - InitialDragPoint.X;

        // Move the Rectangle with the pointer drag
        Rectangle trackSegment = sender as Rectangle;
        trackSegment.Margin = new Thickness(SegmentMargin, 5, 0, 5);
    }
}

This code works great for the mouse, but when I try to use it for touch, I have to press-and-hold to initiate drag, and even then, the rectangle only moves a few units before staying put. 该代码非常适合鼠标使用,但是当我尝试使用它进行触摸时,我必须按住以启动拖动,即使那样,矩形在放置前也只移动了几个单位。 I'm not sure why the behaviors are different. 我不确定为什么行为会有所不同。

Another issue with this code is that, if the rectangle is narrow enough such that when I drag quickly and the rectangle can't keep up with the cursor, it stops dragging when the cursor has left the rectangle boundary. 此代码的另一个问题是,如果矩形足够窄,以至于当我快速拖动并且矩形无法跟上光标时,当光标离开矩形边界时,它将停止拖动。 A much smaller issue than the touch not working, but a little annoying nonetheless. 比触摸无法解决的问题小得多,但仍然有点烦人。

It sounds like the ScrollViewer is capturing the touch events to do its own scrolling. 听起来好像ScrollViewer正在捕获触摸事件以进行自己的滚动。 Insead of handling the manipulations manually you can use Xaml's manipulation engine to register for manipulation events. 您可以使用Xaml的操纵引擎来注册操纵事件,以手动操纵操纵。 This is both easier to code and more efficient. 这不仅更容易编码,而且效率更高。 It will work for touch and mouse by default. 默认情况下,它将适用于触摸和鼠标。

<Rectangle Margin="5" Fill="Orange" Height="100" Width="200"
           ManipulationMode="TranslateX"
           ManipulationDelta="Rectangle_ManipulationDelta"
           >
    <Rectangle.RenderTransform>
        <CompositeTransform />
    </Rectangle.RenderTransform>
</Rectangle>

In the Rectangle_ManipulationDelta method translate the rectangle: 在Rectangle_ManipulationDelta方法中,转换矩形:

private void Rectangle_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
    UIElement elem = sender as UIElement;
    CompositeTransform ct = elem.RenderTransform as CompositeTransform;

    ct.TranslateX += e.Delta.Translation.X;
}

If you only want translations you could use a TranslateTransform instead of a CompositeTransform, or you could add in rotations and scaling. 如果只需要平移,则可以使用TranslateTransform而不是CompositeTransform,或者可以添加旋转和缩放。

See Quickstart: Touch input (XAML) for more on using gestures and manipulation events. 有关使用手势和操纵事件的更多信息,请参见快速入门:触摸输入(XAML)

I discuss the ScrollViewer taking over pointer handling in my blog entry Where did all my gestures go? 我在博客条目中讨论了ScrollViewer接管指针处理的问题我所有的手势都去了哪里? If you really want to handle the pointer events yourself I discuss how to disable the ScrollViewer during dragging. 如果您真的想自己处理指针事件,我将讨论如何在拖动过程中禁用ScrollViewer。 You can handle the case where the finger moves faster than the target by capturing the pointer . 您可以通过捕获指针来处理手指移动快于目标的情况。 This isn't needed if you handle the manipulation events. 如果您处理操作事件,则不需要此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM