Xamarin.Forms - 应用程序级别的全局抽头事件

时间:2016-12-19 04:17:44

标签: c# xamarin xamarin.forms xamarin.android

如何在Xamarin.Forms应用中截取应用级别的点击/点击事件?

我尝试在MainPage上使用类似

的内容
    <Grid.GestureRecognizers>
        <TapGestureRecognizer Command="{Binding TappedCommand}" Tapped="TapGestureRecognizer_OnTapped"></TapGestureRecognizer>
    </Grid.GestureRecognizers>

但只有点击空白区域才有效,触摸按钮不会触发事件。

此外,我经常通过更改MainPage进行导航,因此即使有效,我也必须添加这样的识别器。

我想全局处理我的应用中的任何触摸/点按/点击事件,是否可以在Xamarin.Forms中使用?

2 个答案:

答案 0 :(得分:3)

可以在特定于平台的应用程序中轻松设置,然后使用Xamarin.Forms依赖服务订阅/取消订阅事件。

您在这些事件中捕获的内容取决于您的需求,在此示例中,我只是捕获并记录x / y值。

通用EventArgs类和DP接口:

public class TouchEventArgs<T> : EventArgs
{
    public T EventData { get; private set; }

    public TouchEventArgs(T EventData)
    {
        this.EventData = EventData;
    }
}

public interface IGlobalTouch
{
    void Subscribe(EventHandler handler);
    void Unsubscribe(EventHandler handler);
}

将以下内容添加到MainActivity应用程序的Xamarin.Android

public EventHandler globalTouchHandler;
public override bool DispatchTouchEvent(MotionEvent ev)
{
    globalTouchHandler?.Invoke(null, new TouchEventArgs<Point>(new Point(ev.GetX(), ev.GetY())));
    return base.DispatchTouchEvent(ev);
}

Android依赖项实施:

public class GlobalTouch : IGlobalTouch
{
    public GlobalTouch() {}

    public void Subscribe(EventHandler handler)
    {
        (Forms.Context as MainActivity).globalTouchHandler += handler;
    }

    public void Unsubscribe(EventHandler handler)
    {
        (Forms.Context as MainActivity).globalTouchHandler -= handler;
    }
}

Xamarin.Forms项目中的用法:

DependencyService.Get<IGlobalTouch>().Subscribe((sender, e) =>
{
    var point = (e as TouchEventArgs<Point>).EventData;
    System.Diagnostics.Debug.WriteLine($"{point.X}:{point.Y}");
});

注意:您应该分配一个代理人,以便取消订阅......

输出:

307.628997802734:365.563842773438
309.280151367188:365.197265625
311.883605957031:365.390991210938
312.694641113281:380.148590087891
308.030578613281:387.823364257813
291.513244628906:396.339416503906
286.220489501953:396.339416503906
282.100006103516:396.339416503906

iOS可以使用相同的技术,可以根据您的需要添加TouchesBeganTouchesEndedTouchesMovedTouchesCancelled ....

答案 1 :(得分:1)

使用SushiHangover分辨率,对于iOS,将是这样的:

在AppDelegate.cs中实现IUIGestureRecognizerDelegate

public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IUIGestureRecognizerDelegate
{

在AppDelegate.cs类中的FinishedLaunching方法中,添加以下内容:

Xamarin.Forms.DependencyService.Register<GlobalTouch>();
bool ret = base.FinishedLaunching(app, options);
if (ret)
{
    UITapGestureRecognizer tap = new UITapGestureRecognizer(Self, new ObjCRuntime.Selector("gestureRecognizer:shouldReceiveTouch:"));
    tap.Delegate = (IUIGestureRecognizerDelegate)Self;
    app.KeyWindow.AddGestureRecognizer(tap);
}
return ret;

在AppDelegate.cs中添加此方法:

[Export("gestureRecognizer:shouldReceiveTouch:")]
public bool ShouldReceiveTouch(UIGestureRecognizer gestureRecognizer, UITouch touch)
{
    Xamarin.Forms.DependencyService.Get<IGlobalTouch>().TapScreen();
    return false;
}

将此添加到GlobalTouch:

EventHandler globalTouchHandler;

public void TapScreen()
{
    globalTouchHandler?.Invoke(this, null);
}

将其添加到IGlobalTouch:

void TapScreen();