Xamarin TapGestureRecognizer 在后台点击时触发点击事件
Xamarin TapGestureRecognizer tap event fired on background taps
我遇到了 TapGestureRecognizer 的一些奇怪行为。我有一些简单的 Xamarin 页面,如下所示
<StackLayout>
<Path
ClassId="BottomCone"
Fill="{AppThemeBinding Dark=#333333, Light=#444444}"
Data="{x:Static local:MainPage.BottomConeGeometry}"
BackgroundColor="Red"
>
<Path.GestureRecognizers>
<TapGestureRecognizer Tapped="BottomConeTapped" />
</Path.GestureRecognizers>
</Path>
</StackLayout>
虽然它实际上只是一些简单的闭合形状,但它被 Path 元素淹没了,我在上面有一些点击事件的处理程序。问题是每次我点击路径或其背景时,事件都会触发。当点击发生在路径的背景中时,是否可以不触发点击事件?并触发事件,以防点击事件发生在 Path 元素内。
因此形状具有重叠的“边界”(每个形状周围的矩形)。
一种技术是拥有一组近似于每个形状的矩形。这个概念是让形状本身 InputTransparent
,并有一组重叠的隐形盒子来捕捉触摸。
OverlappingShapeButtonsPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XFSOAnswers.OverlappingShapeButtonsPage">
<ContentPage.Resources>
<Style TargetType="BoxView">
<!-- Uncomment, to see where OnTapped1 boxes are. -->
<!--<Setter Property="BackgroundColor" Value="Red"/>-->
</Style>
</ContentPage.Resources>
<ContentPage.Content>
<Grid>
<AbsoluteLayout InputTransparent="True">
<Polygon Points="0,0 80,0 0,60" Fill="Green" />
<Polygon Points="80,0 80,60 0,60" Fill="Pink" />
</AbsoluteLayout>
<Grid RowDefinitions="20,20,20" ColumnDefinitions="20,20,20,20"
RowSpacing="0" ColumnSpacing="0">
<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapped2" />
</Grid.GestureRecognizers>
<BoxView Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">
<BoxView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapped1" />
</BoxView.GestureRecognizers>
</BoxView>
<BoxView Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
<BoxView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapped1" />
</BoxView.GestureRecognizers>
</BoxView>
<BoxView Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="1">
<BoxView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapped1" />
</BoxView.GestureRecognizers>
</BoxView>
</Grid>
</Grid>
</ContentPage.Content>
</ContentPage>
OverlappingShapeButtonsPage.xaml.cs:
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace XFSOAnswers
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class OverlappingShapeButtonsPage : ContentPage
{
public OverlappingShapeButtonsPage()
{
InitializeComponent();
}
/// <summary>
/// This is called when any of the BoxViews are touched.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void OnTapped1(object sender, EventArgs e)
{
}
/// <summary>
/// This is called when the grid is touched anywhere that is not inside one of the BoxViews.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void OnTapped2(object sender, EventArgs e)
{
}
}
}
用户看到的内容:
红色显示 OnTapped1 的框,近似于绿色三角形:
这相当有效,因为用户倾向于触摸他们感兴趣的形状的中心附近。
您可以通过简单的 (x,y) 数学计算来优化这两个形状之间的边缘。
一般来说,请确保您不会期望用户触摸的精度不切实际。首先,这意味着触摸区域不能太小(小区域超过一个)。
考虑这些(或类似的)准则:Optimal Size and Spacing for Mobile Touch。
我遇到了 TapGestureRecognizer 的一些奇怪行为。我有一些简单的 Xamarin 页面,如下所示
<StackLayout>
<Path
ClassId="BottomCone"
Fill="{AppThemeBinding Dark=#333333, Light=#444444}"
Data="{x:Static local:MainPage.BottomConeGeometry}"
BackgroundColor="Red"
>
<Path.GestureRecognizers>
<TapGestureRecognizer Tapped="BottomConeTapped" />
</Path.GestureRecognizers>
</Path>
</StackLayout>
虽然它实际上只是一些简单的闭合形状,但它被 Path 元素淹没了,我在上面有一些点击事件的处理程序。问题是每次我点击路径或其背景时,事件都会触发。当点击发生在路径的背景中时,是否可以不触发点击事件?并触发事件,以防点击事件发生在 Path 元素内。
因此形状具有重叠的“边界”(每个形状周围的矩形)。
一种技术是拥有一组近似于每个形状的矩形。这个概念是让形状本身 InputTransparent
,并有一组重叠的隐形盒子来捕捉触摸。
OverlappingShapeButtonsPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XFSOAnswers.OverlappingShapeButtonsPage">
<ContentPage.Resources>
<Style TargetType="BoxView">
<!-- Uncomment, to see where OnTapped1 boxes are. -->
<!--<Setter Property="BackgroundColor" Value="Red"/>-->
</Style>
</ContentPage.Resources>
<ContentPage.Content>
<Grid>
<AbsoluteLayout InputTransparent="True">
<Polygon Points="0,0 80,0 0,60" Fill="Green" />
<Polygon Points="80,0 80,60 0,60" Fill="Pink" />
</AbsoluteLayout>
<Grid RowDefinitions="20,20,20" ColumnDefinitions="20,20,20,20"
RowSpacing="0" ColumnSpacing="0">
<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapped2" />
</Grid.GestureRecognizers>
<BoxView Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">
<BoxView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapped1" />
</BoxView.GestureRecognizers>
</BoxView>
<BoxView Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
<BoxView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapped1" />
</BoxView.GestureRecognizers>
</BoxView>
<BoxView Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="1">
<BoxView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapped1" />
</BoxView.GestureRecognizers>
</BoxView>
</Grid>
</Grid>
</ContentPage.Content>
</ContentPage>
OverlappingShapeButtonsPage.xaml.cs:
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace XFSOAnswers
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class OverlappingShapeButtonsPage : ContentPage
{
public OverlappingShapeButtonsPage()
{
InitializeComponent();
}
/// <summary>
/// This is called when any of the BoxViews are touched.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void OnTapped1(object sender, EventArgs e)
{
}
/// <summary>
/// This is called when the grid is touched anywhere that is not inside one of the BoxViews.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void OnTapped2(object sender, EventArgs e)
{
}
}
}
用户看到的内容:
红色显示 OnTapped1 的框,近似于绿色三角形:
这相当有效,因为用户倾向于触摸他们感兴趣的形状的中心附近。
您可以通过简单的 (x,y) 数学计算来优化这两个形状之间的边缘。
一般来说,请确保您不会期望用户触摸的精度不切实际。首先,这意味着触摸区域不能太小(小区域超过一个)。
考虑这些(或类似的)准则:Optimal Size and Spacing for Mobile Touch。