[iOS] Clear the delegate from ContextActionCell (#4324) fixes #4314

* [Controls] Add repo for issue #4341

* [iOS] Clear the global closer delegate from ContextActionCell when disposing

* [Controls] Rename to correct issue number

* [Controls] Try fix opening context menu on iOS10

* [Controls] Add more testing to #4314

* [iOS] Fix Globalcloser when no cell exists
This commit is contained in:
Rui Marinho 2018-11-29 18:03:08 +00:00 коммит произвёл GitHub
Родитель 7ae81e375c
Коммит 028b9f14df
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 88 добавлений и 28 удалений

Просмотреть файл

@ -0,0 +1,57 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
#if UITEST
using Xamarin.Forms.Core.UITests;
using Xamarin.UITest;
using NUnit.Framework;
#endif
namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.ContextActions)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 4314, "When ListView items is removed and it is empty, Xamarin Forms crash", PlatformAffected.iOS)]
public class Issue4314 : TestNavigationPage // or TestMasterDetailPage, etc ...
{
const string Success = "Success";
#if !UITEST
MessagesViewModel viewModel;
protected override void Init()
{
var page = new ContextActionsGallery(false, true, 2) { Title = "Swipe and delete both" };
viewModel = page.BindingContext as MessagesViewModel;
viewModel.Messages.CollectionChanged += (s, e) =>
{
if (viewModel.Messages.Count == 0)
{
Navigation.PushAsync(new ContentPage { Title = "Success", Content = new Label { Text = Success } });
}
};
Navigation.PushAsync(page);
}
#else
protected override void Init()
{
}
#endif
#if UITEST && __IOS__
[Test]
public void Issue4341Test()
{
RunningApp.WaitForElement(c=> c.Marked("Email"));
RunningApp.ActivateContextMenu("Subject Line 0");
RunningApp.WaitForElement("Delete");
RunningApp.Tap("Delete");
RunningApp.ActivateContextMenu("Subject Line 1");
RunningApp.Tap("Delete");
RunningApp.WaitForElement(c=> c.Marked(Success));
RunningApp.Back();
RunningApp.WaitForElement(c => c.Marked("Email"));
RunningApp.SwipeRightToLeft();
}
#endif
}
}

Просмотреть файл

@ -820,6 +820,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Issue3884.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue4001.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue4138.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue4314.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml">

Просмотреть файл

@ -7,9 +7,9 @@ namespace Xamarin.Forms.Controls
{
internal class MessagesViewModel : ViewModelBase
{
public MessagesViewModel()
public MessagesViewModel(int messagesCount)
{
Messages = new ObservableCollection<MessageViewModel> (Enumerable.Range (0, 100).Select (i => {
Messages = new ObservableCollection<MessageViewModel> (Enumerable.Range (0, messagesCount).Select (i => {
return new MessageViewModel { Subject = "Subject Line " + i, MessagePreview = "Lorem ipsum dolorem monkeys bonkers " + i };
}));
@ -26,7 +26,7 @@ namespace Xamarin.Forms.Controls
}
[Preserve (AllMembers = true)]
internal class MessageViewModel : ViewModelBase
public class MessageViewModel : ViewModelBase
{
public MessageViewModel()
{
@ -86,13 +86,16 @@ namespace Xamarin.Forms.Controls
}
}
public ContextActionsGallery (bool tableView = false)
public ContextActionsGallery (bool tableView = false, bool hasUnevenRows = false, int messagesCount = 100)
{
BindingContext = new MessagesViewModel();
BindingContext = new MessagesViewModel(messagesCount);
View list;
if (!tableView) {
list = new ListView();
list = new ListView
{
HasUnevenRows = hasUnevenRows
};
list.SetBinding (ListView.ItemsSourceProperty, "Messages");
((ListView)list).ItemTemplate = new DataTemplate (typeof (MessageCell));
} else {

Просмотреть файл

@ -276,6 +276,7 @@ namespace Xamarin.Forms.Platform.iOS
if (_scroller != null)
{
_scroller.Delegate = null;
_scroller.Dispose();
_scroller = null;
}

Просмотреть файл

@ -125,7 +125,7 @@ namespace Xamarin.Forms.Platform.iOS
RestoreHighlight(scrollView);
s_scrollViewBeingScrolled = null;
ClearCloserRecognizer(scrollView);
ClearCloserRecognizer(GetContextCell(scrollView));
ClosedCallback?.Invoke();
}
}
@ -133,7 +133,7 @@ namespace Xamarin.Forms.Platform.iOS
public void Unhook(UIScrollView scrollView)
{
RestoreHighlight(scrollView);
ClearCloserRecognizer(scrollView);
ClearCloserRecognizer(GetContextCell(scrollView));
}
public override void WillEndDragging(UIScrollView scrollView, PointF velocity, ref PointF targetContentOffset)
@ -158,36 +158,35 @@ namespace Xamarin.Forms.Platform.iOS
while (view.Superview != null)
{
view = view.Superview;
NSAction close = () =>
{
if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
RestoreHighlight(scrollView);
IsOpen = false;
scrollView.SetContentOffset(new PointF(0, 0), true);
ClearCloserRecognizer(scrollView);
};
var table = view as UITableView;
if (table != null)
{
ContextActionsCell contentCell = GetContextCell(scrollView);
NSAction close = () =>
{
if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
RestoreHighlight(scrollView);
IsOpen = false;
scrollView.SetContentOffset(new PointF(0, 0), true);
ClearCloserRecognizer(contentCell);
contentCell = null;
};
_table = table;
_globalCloser = new GlobalCloseContextGestureRecognizer(scrollView, close);
_globalCloser.ShouldRecognizeSimultaneously = (recognizer, r) => r == _table.PanGestureRecognizer;
table.AddGestureRecognizer(_globalCloser);
_closer = new UITapGestureRecognizer(close);
var cell = GetContextCell(scrollView);
cell.ContentCell.AddGestureRecognizer(_closer);
contentCell.AddGestureRecognizer(_closer);
}
}
}
}
else
{
ClearCloserRecognizer(scrollView);
ClearCloserRecognizer(GetContextCell(scrollView));
IsOpen = false;
targetContentOffset = new PointF(0, 0);
@ -234,13 +233,12 @@ namespace Xamarin.Forms.Platform.iOS
base.Dispose(disposing);
}
void ClearCloserRecognizer(UIScrollView scrollView)
void ClearCloserRecognizer(ContextActionsCell cell)
{
if (_globalCloser == null || _globalCloser.State == UIGestureRecognizerState.Cancelled)
return;
var cell = GetContextCell(scrollView);
cell.ContentCell.RemoveGestureRecognizer(_closer);
cell?.ContentCell?.RemoveGestureRecognizer(_closer);
_closer.Dispose();
_closer = null;
@ -252,9 +250,9 @@ namespace Xamarin.Forms.Platform.iOS
ContextActionsCell GetContextCell(UIScrollView scrollView)
{
var view = scrollView.Superview.Superview;
var view = scrollView?.Superview?.Superview;
var cell = view as ContextActionsCell;
while (view.Superview != null)
while (view?.Superview != null)
{
cell = view as ContextActionsCell;
if (cell != null)