This issue is very specific but affects the functionality of SplitButton control in Uno (#2885).
Suppose the following XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button
x:Name="LeftButton"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
Left Button
</Button>
<Button
x:Name="RightButton"
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
Right Button
</Button>
</Grid>
Two stretched buttons in two grid columns.
The code-behind is as follows:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
AttachEvents(LeftButton);
AttachEvents(RightButton);
}
private void AttachEvents(Button button)
{
button.Click += OnClick;
button.PointerEntered += OnPointerEntered;
button.PointerExited += OnPointerExited;
button.PointerPressed += OnPointerPressed;
button.PointerReleased += OnPointerReleased;
button.PointerCanceled += OnPointerCanceled;
button.PointerCaptureLost += OnPointerCaptureLost;
}
private void OnClick(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine(((Button)sender).Name + " was clicked");
}
private void OnPointerEntered(object sender, PointerRoutedEventArgs p)
{
System.Diagnostics.Debug.WriteLine("Entered");
OnPointerEvent();
}
private void OnPointerExited(object sender, PointerRoutedEventArgs p)
{
System.Diagnostics.Debug.WriteLine("Exited");
OnPointerEvent();
}
private void OnPointerMoved(object sender, PointerRoutedEventArgs p)
{
System.Diagnostics.Debug.WriteLine("Moved");
OnPointerEvent();
}
private void OnPointerReleased(object sender, PointerRoutedEventArgs p)
{
System.Diagnostics.Debug.WriteLine("Released");
OnPointerEvent();
}
private void OnPointerPressed(object sender, PointerRoutedEventArgs p)
{
System.Diagnostics.Debug.WriteLine("Pressed");
OnPointerEvent();
}
private void OnPointerCanceled(object sender, PointerRoutedEventArgs p)
{
System.Diagnostics.Debug.WriteLine("Canceled");
OnPointerEvent();
}
private void OnPointerCaptureLost(object sender, PointerRoutedEventArgs p)
{
System.Diagnostics.Debug.WriteLine("CaptureLost");
OnPointerEvent();
}
private void OnPointerEvent()
{
RightButton.SetValue(Grid.ColumnProperty, 0);
RightButton.SetValue(Grid.ColumnSpanProperty, 2);
}
}
On any pointer event, the right button is spanned to cover both columns of the grid. Observe that under Uno, for example on Android and iOS, when the left button area is tapped, Pointer Entered event is called (which makes the right button span), but after this left button's Click event is called.
Note this affects only touch. Mouse and pen will trigger pointer moved before user is able to click, so the button will already be spanned. So macOS is the only one safe here :-D .
On UWP for tap, Pointer entered event is called, which makes the right button span and right button's Click event is called.
See above.
Nuget Package: latest
Package Version(s): dev
Affected platform(s):
Visual Studio:
Relevant plugins:
@dr1rrb is this an existing issue ?
Hum I don't think that we already have a an issue for that.
I've tested that updating the template (visual states) while pointer is pressed would result in acceptable pointers events sequence, but moving elements over another element while pointer is pressed is kind of things I've classified as "stretch case" and didn't validated it.
Thinking about it, it's totally makes sense: When we press the pointer, the Button captures the pointer and it will then receive all pointer events until release. On UWP, they are probably validating that the element is not covered when the pointer is released ... but I'm not sure that we are able to validate that with uno yet (it would requires an API to get all elements at a given coordinate)