我创建了一个自定义控件,该控件使用带有长按动作的按钮。当按钮获得Pressed
时,动作开始。当按钮为Released
时,操作停止。问题在于,一旦按钮为Pressed
,用户就可以选择将手指滑离该按钮。发生这种情况时,Released
事件不会触发,并且由Pressed
事件触发的操作会无限期地运行。
这是我的自定义控件的XAML代码:
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
x:Class="TestProject.NumericUpDown"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Name="this">
<ContentView.Content>
<Button
x:Name="TestButton"
Grid.Row="0"
Grid.Column="0"
Pressed="TestButton_Pressed"
Released="TestButton_Released"
Text="Test" />
</ContentView.Content>
</ContentView>
在后面的代码中,我有以下方法可以测试事件:
private void TestButton_Pressed(object sender, EventArgs e)
{
Console.WriteLine("Pressed");
}
private void TestButton_Released(object sender, EventArgs e)
{
Console.WriteLine("Released");
}
这是我使用用户控件的页面:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="ButtonTest.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:ButtonTest"
xmlns:local="clr-namespace:ButtonTest">
<ScrollView>
<StackLayout Orientation="Vertical">
<local:TestControl />
</StackLayout>
</ScrollView>
</ContentPage>
我已阅读到,按下和释放动作可能会发生中途改变,因为它变成了滑动动作。但是如何检测到这一点,以便取消由Pressed
事件开始的操作?
更新:此问题似乎与版本有关。我的项目适用于最新的Xamarin版本4.3。 Visual Studio 2019默认为Xamarin 3.4,它没有此问题!如果要测试此问题,请使用Xamarin 3.6或更高版本。
更新2 :我已添加页面XAML代码。这包括似乎是问题根源的ScrollView。 StackLayout不存在此问题。
答案 0 :(得分:0)
我有类似的问题。那就是我来的:
public class CustomButtonRenderer : ButtonRenderer
{
public CustomButtonRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (Control != null && e.NewElement != null)
{
Control.Touch += OnTouch;
}
}
private void OnTouch(object sender, TouchEventArgs args)
{
var buttonController = (IButtonController)Element;
if (buttonController == null)
return;
var x = (int) args.Event.GetX();
var y = (int) args.Event.GetY();
if (!TouchInsideControl(x, y))
{
buttonController.SendReleased();
}
else if (args.Event.Action == MotionEventActions.Down)
{
buttonController.SendPressed();
}
else if (args.Event.Action == MotionEventActions.Up)
{
buttonController.SendReleased();
buttonController.SendClicked();
}
}
private bool TouchInsideControl(int x, int y)
{
return x <= Control.Right && x >= Control.Left && y <= Control.Bottom && y >= Control.Top;
}
}