【问题标题】:Xamarin TapGestureRecognizer tap event fired on background tapsXamarin TapGestureRecognizer 在后台点击时触发点击事件
【发布时间】:2022-01-03 16:02:24
【问题描述】:

我遇到了 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 元素内发生点击事件。

【问题讨论】:

  • 我在 Xamarin Forms 的任何地方都看不到对此的任何支持。就此而言,我在 Android 中看不到它(不使用 Xamarin 时),因此 Xamarin 不支持它也就不足为奇了。我能想到的最简单的技巧是手动定义一个近似路径形状的圆(或椭圆)。然后当得到点击事件时,做你自己的数学来确定它是否在那个圆圈内。或者更一般地说,en.wikipedia.org/wiki/Point_in_polygon
  • 触摸通常被认为是一种“近似”用户操作。也就是说,我们想知道用户的意图是什么,而不一定要知道他们的手指是否完全适合给定的形状。详细说明您的设计目标,让您关心触摸是否在可见形状内,而不是在包围形状的矩形内。
  • @ToolmakerSteve 我相信在同一个屏幕上有多个可以触摸的按钮是完全可以的。那有什么问题?当你有一个按钮时,我相信你想知道用户是点击了按钮还是按钮外的某个地方,对吗?我的目的是一样的,唯一的区别是我的按钮有不同的形式,用路径形状描述。遗憾的是,我们无法区分用户是触摸了按钮还是触摸了按钮之外的某个地方。
  • 嗯?我的观点是,通常人们想知道某人按下了 哪个 按钮,而不是他们是否设法准确地触摸了与按钮形状匹配的像素。你还没有解释为什么它对你的应用很重要。如果用户大约在按钮区域内触摸屏幕,则最可能的意图是“我正在尝试触摸此按钮”。不要让它变得比必要的更难。
  • @ToolmakerSteve 对,当您有标准格式的按钮时,它可以工作。但是,当您有一个彼此靠近的非标准按钮的相对布局时,背景会相互叠加,但绘制的按钮本身不会叠加,当您按下一个按钮时,您会从另一个按钮获取处理程序

标签: xamarin xamarin.forms


【解决方案1】:

因此形状具有重叠的“边界”(每个形状周围的矩形)。

一种技术是使用一组近似于每个形状的矩形。这个概念是让形状本身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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2015-04-28
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多