Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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,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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down
15 changes: 9 additions & 6 deletions Xamarin.Forms.Controls/GalleryPages/EditableList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
}));

Expand All @@ -26,7 +26,7 @@ public ObservableCollection<MessageViewModel> Messages
}

[Preserve (AllMembers = true)]
internal class MessageViewModel : ViewModelBase
public class MessageViewModel : ViewModelBase
{
public MessageViewModel()
{
Expand Down Expand Up @@ -86,13 +86,16 @@ public MessageCell()
}
}

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 {
Expand Down
1 change: 1 addition & 0 deletions Xamarin.Forms.Platform.iOS/ContextActionCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ protected override void Dispose(bool disposing)

if (_scroller != null)
{
_scroller.Delegate = null;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only real change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what's all this other stuff?

_scroller.Dispose();
_scroller = null;
}
Expand Down
42 changes: 20 additions & 22 deletions Xamarin.Forms.Platform.iOS/ContextScrollViewDelegate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,15 @@ public override void Scrolled(UIScrollView scrollView)
RestoreHighlight(scrollView);

s_scrollViewBeingScrolled = null;
ClearCloserRecognizer(scrollView);
ClearCloserRecognizer(GetContextCell(scrollView));
ClosedCallback?.Invoke();
}
}

public void Unhook(UIScrollView scrollView)
{
RestoreHighlight(scrollView);
ClearCloserRecognizer(scrollView);
ClearCloserRecognizer(GetContextCell(scrollView));
}

public override void WillEndDragging(UIScrollView scrollView, PointF velocity, ref PointF targetContentOffset)
Expand All @@ -158,36 +158,35 @@ public override void WillEndDragging(UIScrollView scrollView, PointF velocity, r
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);
Expand Down Expand Up @@ -234,13 +233,12 @@ protected override void Dispose(bool disposing)
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;

Expand All @@ -252,9 +250,9 @@ void ClearCloserRecognizer(UIScrollView scrollView)

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)
Expand Down