Skip to content
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
39 changes: 39 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue26328.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" ?>
<controls:TestContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:Maui.Controls.Sample.Issues"
xmlns:cmp="clr-namespace:Microsoft.Maui.Controls.Compatibility;assembly=Microsoft.Maui.Controls"
x:Class="Maui.Controls.Sample.Issues.Issue26328">
<ContentPage.Content>
<CollectionView AutomationId="TestCollectionView"
ItemsSource="{Binding ItemList}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="controls:Issue26328ItemModel">
<SwipeView>
<Border Padding="10,30">
<Label>
<Label.Text>
<MultiBinding Converter="{controls:Issue26328TestConverter}">
<Binding x:DataType="controls:Issue26328ItemModel" Path="Id" />
<Binding x:DataType="controls:Issue26328ItemModel" Path="Title" />
</MultiBinding>
</Label.Text>
</Label>
</Border>
<SwipeView.RightItems>
<SwipeItems Mode="Execute">
<SwipeItemView Command="{Binding SwipeCommand}">
<ContentView Padding="10"
HorizontalOptions="End"
VerticalOptions="Center">
<Label Text="X" />
</ContentView>
</SwipeItemView>
</SwipeItems>
</SwipeView.RightItems>
</SwipeView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage.Content>
</controls:TestContentPage>
99 changes: 99 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue26328.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System.Collections.ObjectModel;
using System.Globalization;

namespace Maui.Controls.Sample.Issues
{
[Issue(IssueTracker.Github, 26328, "SwipeView causes Java.Lang.IllegalArgumentException: Cannot add a null child view to a ViewGroup", PlatformAffected.Android)]
public partial class Issue26328 : TestContentPage
{
public Issue26328()
{
InitializeComponent();
}

protected override void Init()
{
BindingContext = new Issue26328ViewModel();
}
}

public class Issue26328ItemModel
{
public int Id { get; set; }
public string Title { get; set; }

public Issue26328ItemModel(int i)
{
Id = i;
Title = "Hello";
}

public Command SwipeCommand =>
new Command(DeleteMessage);

void DeleteMessage()
{
#pragma warning disable CS0618 // Type or member is obsolete
MessagingCenter.Send<Issue26328ItemModel, Issue26328RemoveMessage>(this, "Swipe", new Issue26328RemoveMessage(this));
#pragma warning disable CS0618 // Type or member is obsolete
}
}

public class Issue26328RemoveMessage
{
public Issue26328ItemModel Item { get; }

public Issue26328RemoveMessage(Issue26328ItemModel item)
{
Item = item;
}
}

public class Issue26328ViewModel
{
public ObservableCollection<Issue26328ItemModel> ItemList { get; set; }

public Issue26328ViewModel()
{
#pragma warning disable CS0618 // Type or member is obsolete
MessagingCenter.Subscribe<Issue26328ItemModel, Issue26328RemoveMessage>(this, "Swipe", (sender, arg) => RemoveItem(arg.Item));
#pragma warning disable CS0618 // Type or member is obsolete
ItemList = [];
for (var i = 0; i < 200; ++i)
{
ItemList.Add(new Issue26328ItemModel(i));
}
}

void RemoveItem(Issue26328ItemModel item)
{
ItemList.Remove(item);
GC.Collect();
}
}

[AcceptEmptyServiceProvider]
public class Issue26328TestConverter : IMultiValueConverter, IMarkupExtension
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] == null || values[1] == null)
{
return null;
}
var id = (int)values[0];
var title = (string)values[1];
return $"{title} - {id}";
}

public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}

public object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#if ANDROID // Crash only happened on Android
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue26328 : _IssuesUITest
{
public override string Issue => "SwipeView causes Java.Lang.IllegalArgumentException: Cannot add a null child view to a ViewGroup";

public Issue26328(TestDevice device)
: base(device)
{ }

[Test]
[Category(UITestCategories.SwipeView)]
public void NoCrashRemovingSwipeItems()
{
App.WaitForElement("TestCollectionView");

for(int i = 0; i < 10; i++)
{
App.SwipeRightToLeft();
App.ScrollDown("TestCollectionView", ScrollStrategy.Gesture, swipePercentage: 0.2);
App.ScrollUp("TestCollectionView", ScrollStrategy.Gesture, swipePercentage: 0.2);
}
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public static void MapVisibility(ISwipeItemViewHandler handler, ISwipeItemView v
protected override void DisconnectHandler(ContentViewGroup platformView)
{
// If we're being disconnected from the xplat element, then we should no longer be managing its children
platformView.CrossPlatformLayout = null;
platformView.RemoveAllViews();
base.DisconnectHandler(platformView);
}
Expand Down
31 changes: 17 additions & 14 deletions src/Core/src/Platform/Android/MauiSwipeView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ float GetSwipeContentOffset()

void UpdateSwipeItems()
{
if (_contentView == null || _actionView != null)
if (_contentView == null || _contentView.IsDisposed() || _actionView != null)
return;

ISwipeItems? items = GetSwipeItemsByDirection();
Expand All @@ -545,22 +545,25 @@ void UpdateSwipeItems()

foreach (var item in items)
{
AView swipeItem = item.ToPlatform(MauiContext);
AView? swipeItem = item?.ToPlatform(MauiContext);

if (item is ISwipeItemView formsSwipeItemView)
if (swipeItem is not null)
{
_actionView.AddView(swipeItem);
UpdateSwipeItemViewLayout(formsSwipeItemView);
_swipeItems.Add(formsSwipeItemView, swipeItem);
}
else if (item is ISwipeItemMenuItem menuItem)
{
_actionView.AddView(swipeItem);
_swipeItems.Add(item, swipeItem);
}
if (item is ISwipeItemView formsSwipeItemView)
{
_actionView.AddView(swipeItem);
UpdateSwipeItemViewLayout(formsSwipeItemView);
_swipeItems.Add(formsSwipeItemView, swipeItem);
}
else if (item is ISwipeItemMenuItem menuItem)
{
_actionView.AddView(swipeItem);
_swipeItems.Add(item, swipeItem);
}

if (swipeItem != null)
swipeItems.Add(swipeItem);
if (swipeItem != null)
swipeItems.Add(swipeItem);
}
}

AddView(_actionView);
Expand Down
Loading