简体   繁体   English

如何在 Xamarin.UWP 应用程序中实现 LongPress?

[英]How do I implement LongPress in a Xamarin.UWP application?

I am trying to implement a custom PlatformEffect that will be execute when the user holds down a Control for a long time for my Xamarin.UWP .我正在尝试实现一个自定义PlatformEffect ,当用户为我的Xamarin.UWP长时间按住 Control 时将执行该自定义PlatformEffect However I found that my application does not respond to mouse clicks.但是我发现我的应用程序没有响应鼠标点击。 I read that I need to change the GestureSettings for the application according to the Remarks here to fix this.我读到我需要根据此处的备注更改应用程序的GestureSettings以解决此问题。 Problem is I don't know how I can do that for a Xamarin.UWP application, any ideas would be very helpful.问题是我不知道如何为 Xamarin.UWP 应用程序做到这一点,任何想法都会非常有帮助。

How do I change the GestureSettings for a Xamarin.UWP application?如何更改 Xamarin.UWP 应用程序的 GestureSettings?

Derive from official document , Touch can produce a Holding action, but mouse devices generally can't.来自官方文档Touch 可以产生一个Holding 动作,但是鼠标设备一般不能。 So, if you want to implement mouse holding, you need use add GestureRecognizer for your element and use GestureRecognizer's holding event to implement mouse holding.因此,如果要实现鼠标按住,则需要为元素添加GestureRecognizer并使用 GestureRecognizer 的保持事件来实现鼠标按住。 For more detail please refer the following.详情请参阅以下内容。

public static class MouseHoldingEffect
{

    public static readonly BindableProperty MouseHoldingProperty =
    BindableProperty.CreateAttached("MouseHolding", typeof(Action), typeof(MouseHoldingEffect), default(Action), propertyChanged: OnhandlerChanged);


    public static Action GetMouseHolding(BindableObject view)
    {
        return (Action)view.GetValue(MouseHoldingProperty);
    }


    public static void SetMouseHolding(BindableObject view, Action value)
    {
        view.SetValue(MouseHoldingProperty, value);
    }

    static void OnhandlerChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var view = bindable as View;
        if (view == null)
        {
            return;
        }

        Action action = (Action)newValue;
        if (action != null)
        {
            view.Effects.Add(new ControlTooltipEffect());
        }
        else
        {
            var toRemove = view.Effects.FirstOrDefault(e => e is ControlTooltipEffect);
            if (toRemove != null)
            {
                view.Effects.Remove(toRemove);
            }
        }
    }

    class ControlTooltipEffect : RoutingEffect
    {
        public ControlTooltipEffect() : base($"Microsoft.{nameof(MouseHoldingEffect)}")
        {

        }
    }
}

UWPMouseEffect UWP 鼠标效果

public class UWPMouseEffect : PlatformEffect
{
    Windows.UI.Input.GestureRecognizer recognizer;
    ManipulationInputProcessor manipulationProcessor;
   
    protected override void OnAttached()
    {
        var control = Control ?? Container;

        if (control is UIElement)
        {
            var mouseHolding = Element.GetValue(MouseHoldingEffect.MouseHoldingProperty) as Action;
            var target = control as UIElement;
            var parent = Window.Current.Content;
            recognizer = new Windows.UI.Input.GestureRecognizer();
            manipulationProcessor = new ManipulationInputProcessor(recognizer, target, parent, mouseHolding);
        }
    }

    protected override void OnDetached()
    {

    }
}

class ManipulationInputProcessor
{
    Action mouseHolding;
    Windows.UI.Input.GestureRecognizer recognizer;
    UIElement element;
    UIElement reference;
    TransformGroup cumulativeTransform;
    MatrixTransform previousTransform;
    CompositeTransform deltaTransform;
    public ManipulationInputProcessor(Windows.UI.Input.GestureRecognizer gestureRecognizer, UIElement target, UIElement referenceFrame, Action holdingAction)
    {
        recognizer = gestureRecognizer;
        element = target;
        reference = referenceFrame;
        mouseHolding = holdingAction;
        // Initialize the transforms that will be used to manipulate the shape
        InitializeTransforms();

        // The GestureSettings property dictates what manipulation events the
        // Gesture Recognizer will listen to.  This will set it to a limited
        // subset of these events.
        recognizer.GestureSettings = GenerateDefaultSettings();

        // Set up pointer event handlers. These receive input events that are used by the gesture recognizer.
        element.PointerPressed += OnPointerPressed;
        element.PointerMoved += OnPointerMoved;
        element.PointerReleased += OnPointerReleased;
        element.PointerCanceled += OnPointerCanceled;


        recognizer.Holding += Recognizer_Holding;

    }

    private void OnPointerMoved(object sender, PointerRoutedEventArgs e)
    {
        recognizer.ProcessMoveEvents(e.GetIntermediatePoints(reference));
    }

    private void OnPointerCanceled(object sender, PointerRoutedEventArgs e)
    {
        recognizer.CompleteGesture();
        element.ReleasePointerCapture(e.Pointer);
    }

    private void OnPointerReleased(object sender, PointerRoutedEventArgs e)
    {
        recognizer.ProcessUpEvent(e.GetCurrentPoint(reference));

        // Release the pointer
        element.ReleasePointerCapture(e.Pointer);
    }

    private void OnPointerPressed(object sender, PointerRoutedEventArgs e)
    {
        element.CapturePointer(e.Pointer);
        // Feed the current point into the gesture recognizer as a down event
        recognizer.ProcessDownEvent(e.GetCurrentPoint(reference));
    }

    private GestureSettings GenerateDefaultSettings()
    {
        return GestureSettings.HoldWithMouse;
    }

    private void Recognizer_Holding(Windows.UI.Input.GestureRecognizer sender, HoldingEventArgs args)
    {
        System.Diagnostics.Debug.WriteLine("-----------Holding---------");
        mouseHolding();
    }

    private void InitializeTransforms()
    {
        cumulativeTransform = new TransformGroup();
        deltaTransform = new CompositeTransform();
        previousTransform = new MatrixTransform() { Matrix = Matrix.Identity };

        cumulativeTransform.Children.Add(previousTransform);
        cumulativeTransform.Children.Add(deltaTransform);

        element.RenderTransform = cumulativeTransform;
    }
}

Usage用法

<StackLayout>
    <Label
        effect:MouseHoldingEffect.MouseHolding="{Binding MouseHoldingAction}"
        FontSize="25"
        Text="Hello" VerticalOptions="Center" HorizontalOptions="Center" Margin="100"/>
</StackLayout>

ViewModel视图模型

public class ViewModel : INotifyPropertyChanged, IDisposable
{
    public ViewModel()
    {
        MouseHolding(() =>
        {
            // do some stuff

        });
    }
    public Action MouseHoldingAction { set; get; }

    public event PropertyChangedEventHandler PropertyChanged;

    public void Dispose()
    {
        
    }

    public void MouseHolding(Action action)
    {
        MouseHoldingAction = action;
    }

}

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

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