Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

[iOS] If SwipeView is disabled, tap gesture events are not firing #12942

Merged
merged 6 commits into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8" ?>
<controls:TestContentPage
xmlns:controls="clr-namespace:Xamarin.Forms.Controls"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Xamarin.Forms.Controls.Issues.Issue11969"
Title="Issue 11969">
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Padding="12"
BackgroundColor="Black"
TextColor="White">
<Label.FormattedText>
<FormattedString>
<Span
Text="Disabling the SwipeView should disable the swipe gesture, but not the interaction with the content. If you want to disable the interaction with the content, must disable the Content."/>
<Span
Text="The behavior must be the same on Android, iOS."/>
<Span
FontAttributes="Bold"
Text="NOTE: Test in simulator and device."/>
</FormattedString>
</Label.FormattedText>
</Label>
<Grid
Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<CheckBox
x:Name="SwipeViewCheckBox"
AutomationId="SwipeViewCheckBoxId"
VerticalOptions="Center"/>
<Label
Grid.Column="1"
Text="SwipeView IsEnabled"
VerticalOptions="Center"/>
<CheckBox
Grid.Row="1"
x:Name="SwipeViewContentCheckBox"
AutomationId="SwipeViewContentCheckBoxId"
VerticalOptions="Center"/>
<Label
Grid.Column="1"
Grid.Row="1"
Text="SwipeView Content IsEnabled"
VerticalOptions="Center"/>
</Grid>
<Label
Grid.Row="2"
x:Name="TestLabel"
AutomationId="TestPassId"
Padding="12"
BackgroundColor="Black"
TextColor="White"
Text="SwipeView Button not tapped"/>
<CollectionView
Grid.Row="3"
x:Name="collectionView"
SelectionChanged="OnCollectionViewSelectionChanged">
<CollectionView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
</x:Array>
</CollectionView.ItemsSource>
<CollectionView.ItemTemplate>
<DataTemplate>
<SwipeView
AutomationId="SwipeViewId"
SwipeStarted="OnSwipeViewSwipeStarted"
SwipeEnded="OnSwipeViewSwipeEnded"
IsEnabled="{Binding Source={x:Reference SwipeViewCheckBox}, Path=IsChecked}">
<SwipeView.LeftItems>
<SwipeItems
SwipeBehaviorOnInvoked="Close"
Mode="Reveal">
<SwipeItem
Text="Favorite"
IconImageSource="coffee.png"
BackgroundColor="LightGreen"/>
<SwipeItem
Text="Delete"
IconImageSource="coffee.png"
BackgroundColor="LightPink" />
</SwipeItems>
</SwipeView.LeftItems>
<Grid
IsEnabled="{Binding Source={x:Reference SwipeViewContentCheckBox}, Path=IsChecked}"
BackgroundColor="White"
Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Text="{Binding}"
FontAttributes="Bold" />
<Button
AutomationId="SwipeButtonId"
Grid.Row="1"
BackgroundColor="Gray"
TextColor="White"
Text="Execute"
Clicked="OnButtonClicked" />
</Grid>
</SwipeView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage.Content>
</controls:TestContentPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using System.Diagnostics;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;

#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
using Xamarin.Forms.Core.UITests;
#endif

namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.Shape)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 11969,
"[Bug] Disabling Swipe view not handling tap gesture events on the content in iOS of Xamarin Forms",
PlatformAffected.iOS)]
public partial class Issue11969 : TestContentPage
{
const string SwipeViewId = "SwipeViewId";
const string SwipeButtonId = "SwipeButtonId";

const string Failed = "SwipeView Button not tapped";
const string Success = "SUCCESS";

public Issue11969()
{
#if APP
InitializeComponent();
#endif
}

protected override void Init()
{

}

#if APP
void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
Debug.WriteLine("CollectionView SelectionChanged");
}

void OnSwipeViewSwipeStarted(object sender, SwipeStartedEventArgs e)
{
Debug.WriteLine("SwipeView SwipeStarted");
}

void OnSwipeViewSwipeEnded(object sender, SwipeEndedEventArgs e)
{
Debug.WriteLine("SwipeView SwipeEnded");
}

void OnButtonClicked(object sender, EventArgs e)
{
Debug.WriteLine("Button Clicked");
TestLabel.Text = Success;
DisplayAlert("Issue 11969", "Button Clicked", "Ok");
}
#endif

#if UITEST && __IOS__
[Test]
[Category(UITestCategories.SwipeView)]
public void SwipeDisableChildButton()
{
RunningApp.WaitForElement(SwipeViewId);
RunningApp.Tap(SwipeButtonId);
RunningApp.WaitForElement(q => q.Marked(Failed));
RunningApp.Tap("SwipeViewCheckBoxId");
RunningApp.Tap(SwipeButtonId);
RunningApp.WaitForElement(q => q.Marked(Failed));
RunningApp.Tap("SwipeViewContentCheckBox");
RunningApp.Tap(SwipeButtonId);
RunningApp.WaitForElement(q => q.Marked(Success));
}
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1658,6 +1658,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Issue8988.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue12084.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue12512.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue11969.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue12685.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue12642.cs" />
</ItemGroup>
Expand Down Expand Up @@ -2017,6 +2018,9 @@
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue12084.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue11969.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla27417Xaml.xaml">
Expand Down
37 changes: 29 additions & 8 deletions Xamarin.Forms.Platform.iOS/Renderers/SwipeViewRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ protected override void Dispose(bool disposing)
{
Element.OpenRequested -= OnOpenRequested;
Element.CloseRequested -= OnCloseRequested;

if (Element.Content != null)
Element.Content.PropertyChanged -= OnContentPropertyChanged;
}

if (_scrollParent != null)
Expand Down Expand Up @@ -273,10 +276,13 @@ public override UIView HitTest(CGPoint point, UIEvent uievent)

foreach (var subview in Subviews)
{
var view = HitTest(subview, point, uievent);
if (subview.UserInteractionEnabled)
{
var view = HitTest(subview, point, uievent);

if (view != null)
return view;
if (view != null)
return view;
}
}

return base.HitTest(point, uievent);
Expand All @@ -289,12 +295,15 @@ UIView HitTest(UIView view, CGPoint point, UIEvent uievent)

foreach (var subview in view.Subviews)
{
CGPoint subPoint = subview.ConvertPointFromView(point, this);
UIView result = subview.HitTest(subPoint, uievent);

if (result != null)
if (subview.UserInteractionEnabled)
{
return result;
CGPoint subPoint = subview.ConvertPointFromView(point, this);
UIView result = subview.HitTest(subPoint, uievent);

if (result != null)
{
return result;
}
}
}

Expand All @@ -317,6 +326,8 @@ void UpdateContent()
}
else
{
Element.Content.PropertyChanged += OnContentPropertyChanged;

if (Subviews.Length > 0)
_contentView = Subviews[0];
}
Expand All @@ -325,6 +336,12 @@ void UpdateContent()
BringSubviewToFront(_contentView);
}

void OnContentPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
UpdateIsSwipeEnabled();
}

void HandleTap()
{
if (_tapGestureRecognizer == null)
Expand Down Expand Up @@ -398,7 +415,11 @@ UIView CreateEmptyContent()

void UpdateIsSwipeEnabled()
{
UserInteractionEnabled = true;
_isSwipeEnabled = Element.IsEnabled;

var isContentEnabled = Element.Content.IsEnabled;
_contentView.UserInteractionEnabled = isContentEnabled;
}

bool IsHorizontalSwipe()
Expand Down