Unplanned
Last Updated: 22 Jul 2025 06:07 by ADMIN
Luis
Created on: 16 Jul 2025 12:48
Category: WrapLayout
Type: Bug Report
2
WrapLayout: [Android] Exception in custom scenario when setting width to the items inside the control via the SizeChanged event

Ran into this issue - which seems to be dependent on how the content gets rendered, so it will fail 100% of the time on specific configurations, resulting in unusable applications.

I've found this issue on Android but there's no telling if the issue is cross platform - as it may depend on item sizings and layout, it may also be reproducible on other platforms, I just haven't hit it yet. The device you run it on may also influence the result, as different resolutions and scalings will impact how items are rendered on screen. I've reproduced this on a Pixel 7 (real device), Samsung A21s (real device) and Pixel 7 Pro (emulator).

Repro steps

  1. Create a new maui sample app, with the relevant Telerik components/initialisation.
  2. Add the xaml and code shown below to the MainPage.
  3. Run the application
  4. OBSERVE
    1. ArgumentOutOfRangeException will be thrown in RadWrapLayoutManager.ArrangeChildren
  5. Stop the app. Comment out the last item being added to the wrap layout and run the app again.
  6. OBSERVE
    1. It will run fine.

MainPage.xaml - use this as the page content:

    <ScrollView Padding="15,0,15,15">
        <VerticalStackLayout Spacing="25">
            <telerik:RadWrapLayout
                x:Name="BrokenLayout"
                Margin="-5"
                SizeChanged="BrokenLayout_SizeChanged"
                StretchLastChild="False">
                <BindableLayout.ItemTemplate>
                    <DataTemplate>
                        <Grid
                            Margin="3.75"
                            Padding="3.75"
                            BackgroundColor="LightGreen">
                            <Label
                                FontAttributes="Bold"
                                FontSize="11"
                                LineBreakMode="TailTruncation"
                                MaxLines="2"
                                Text="{Binding}"
                                VerticalOptions="End" />
                        </Grid>
                    </DataTemplate>
                </BindableLayout.ItemTemplate>
            </telerik:RadWrapLayout>
        </VerticalStackLayout>
    </ScrollView>

MainPage.xaml.cs code

    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            List<string> items = new List<string>();

            items.Add("TSONE");
            items.Add("N ANCETOIDO");
            items.Add("ADDKNEDEGO LW");
            items.Add("A EFCTTLIAH");
            items.Add("OHACP HTATTO");
            items.Add("AASESII NAYXB/RFKL");
            items.Add("EMIQULENOCE PTCTL");
            items.Add("SCNSTUGRRIOEMA TEU");
            items.Add("EPEENSX");
            items.Add("BRUXEROL TAA");
            items.Add("TVLRETAAX ER");
            items.Add("SMA SELISD");
            items.Add("NIAEGOEEATIRUPR SVT");
            items.Add("CTPLRCELT AO");
            items.Add("REAREPTIRDQ U");
            items.Add("ASEDP TUR");
            items.Add("CJTEUT ORPDEAP");
            items.Add(" CECCRNTARODTO");
            items.Add("- FLEOUTEQRUOPWSL");
            items.Add("PINTRNMEU REEQTU");
            items.Add("RE LWSRANKOGIO TNT");
            items.Add("KAREBTA KE");
            items.Add("ITTANIW MIEG"); // comment out this one and it'll run fine. keep it and it'll fail.

            BindableLayout.SetItemsSource(this.BrokenLayout, items);
        }

        private double _width = 0;
        private double minItemWidth = 110.0;
        private double maxItemWidth = 160.0;

        private void BrokenLayout_SizeChanged(object sender, EventArgs e)
        {
            if (sender is RadWrapLayout wl
                && wl.Width > 0 
                && (int)Math.Floor(wl.Width) is int widthInt
                && widthInt != this._width)
            {
                this._width = widthInt;

                double? candidateItemWidth = null;
                var itemCount = wl.Children.Count;

                if (itemCount > 0 && itemCount * maxItemWidth >= widthInt)
                {
                    var columnCount = (int)Math.Ceiling(widthInt / maxItemWidth);

                    candidateItemWidth = (int)Math.Floor((double)widthInt / columnCount);

                    if (candidateItemWidth > 1.25 * maxItemWidth)
                    {
                        columnCount += 1;
                        candidateItemWidth = (int)Math.Floor((double)widthInt / columnCount);
                    }
                    else if (candidateItemWidth < minItemWidth)
                    {
                        columnCount -= 1;
                        candidateItemWidth = (int)Math.Floor((double)widthInt / columnCount);
                    }
                }

                wl.ItemWidth = candidateItemWidth ?? maxItemWidth;
            }
        }
    }

Error:

System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')'

 	0xFFFFFFFFFFFFFFFF in Android.Runtime.RuntimeNativeMethods.monodroid_debugger_unhandled_exception	C#
 	0x1A in Android.Runtime.JNINativeWrapper._unhandled_exception at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:12,5	C#
 	0x26 in Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPZIIII_V at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:441,26	C#
 	0x8 in System.ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException	C#
 	0x9 in System.Collections.Generic.List<double>.get_Item	C#
 	0x205 in Telerik.Maui.RadWrapLayoutManager.ArrangeChildren	C#

 
6 comments
ADMIN
Didi
Posted on: 22 Jul 2025 06:07

Hi Luis,

I have tested the scenario on Pixel 5 and 7 emulators Android API 35 and 33, with vertical stack the app crashes on these emulators. I removed the stack and no issues. On WinUI no crash with and without the stack. I created a Pixel 7 pro emulator API 35 and tested my sample app without stack in the xaml and the exception still occurs.

I have changed the status of this item to Unplanned. For now the workaround is using a dispatcher. It seems the control does not behave as expected when changing its child items width runtime and the behavior happens on specific Android devices. 

Regards,
Didi
Progress Telerik

Luis
Posted on: 21 Jul 2025 14:13
It still consistently fails for me...
ADMIN
Didi
Posted on: 21 Jul 2025 14:06

Hi Luis,

I have further research this and you can remove the vertical stack from the xaml code and the dispatcher from the event handler and the WrapLayout control behaves as expected, no exception. Give this test a try and let me know the results. 

I know the dispatcher is a workaround for the case, however, I tested many scenarios and it seems the behavior is provoked from the stack layout. There are cases and scenarios when using stack layout is not the best approach as it does not provide enough space for the controls to fill into. 

Regards,
Didi
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Luis
Posted on: 21 Jul 2025 10:32

At first glance using the dispatcher around the line that sets the item width appears to stop it failing.
However it does seem to result in the UI visibly loading with one size and then changing to the newer size as the dimension update is done much later. no such flickering with the old code.

This dispatcher inclusion is therefore a workaround that could get stuff working for some, but not really the best outcome for this application.
Would be great to see the code be made more robust :)

ADMIN
Didi
Posted on: 21 Jul 2025 09:10

Hello Luis and Garry,

Thank you for all details and information on this case.

I have reproduced the issue only on Android when using the SizeChanged event to define different width to the items. I have debugged the scenario and at the exception occurs at the time the items size changes. But at this time the control measures the items. 

As a solution could you please add a dispatcher and let me know whether it works on your side: 

This is the code on my side:

private void BrokenLayout_SizeChanged(object sender, EventArgs e)
{
	Dispatcher.Dispatch(() =>
	{
		if (sender is RadWrapLayout wl
		&& wl.Width > 0
		&& (int)Math.Floor(wl.Width) is int widthInt
		&& widthInt != this._width)
		{
			this._width = widthInt;

			double? candidateItemWidth = null;
			var itemCount = wl.Children.Count;

			if (itemCount > 0 && itemCount * maxItemWidth >= widthInt)
			{
				var columnCount = (int)Math.Ceiling(widthInt / maxItemWidth);

				candidateItemWidth = (int)Math.Floor((double)widthInt / columnCount);

				if (candidateItemWidth > 1.25 * maxItemWidth)
				{
					columnCount += 1;
					candidateItemWidth = (int)Math.Floor((double)widthInt / columnCount);
				}
				else if (candidateItemWidth < minItemWidth)
				{
					columnCount -= 1;
					candidateItemWidth = (int)Math.Floor((double)widthInt / columnCount);
				}
			}

			wl.ItemWidth = candidateItemWidth ?? maxItemWidth;
		}
	});
			
}

Regards,
Didi
Progress Telerik

Garry
Posted on: 17 Jul 2025 07:22

The cause of this crash seems to be when you have a series of items `RadWrapLayout` they take up only the size they need. If you then change the size to make them all take up an equal amount of space it can push items onto a new row.

The `RadWrapLayoutManager.ArrangeChildren` method does not handle that scenario well and tries to get the height (or width) of a length from the `lengths` array that is outside the range of the collection causing the error above.

Having the method be more robust and handle items changing size and potentially pushing them onto new rows (or columns) would be ideal for us.