Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
021053a
[Testing] Feature Matrix UITest Cases for Shell Flyout Page (#32525)
NafeelaNazhir Feb 23, 2026
d93eb70
[Android, Windows] Fix for FlyoutPage toolbar button not updating on …
praveenkumarkarunanithi Feb 23, 2026
47b9d94
Fix for First Item in CollectionView Overlaps in FlyoutPage.Flyout on…
praveenkumarkarunanithi Feb 23, 2026
dc75f76
[Android] Fix RemainingItemsThresholdReachedCommand not firing when C…
SuthiYuvaraj Feb 23, 2026
5d71c59
[Windows] Fixed IsEnabled Property not works on Tabs (#26728)
NirmalKumarYuvaraj Feb 23, 2026
7f3e760
Bumps Syncfusion.Maui.Toolkit dependency to version 1.0.9 (#34178)
PaulAndersonS Feb 23, 2026
bbd7f28
[iOS] Fix toolbar items ignoring BarTextColor on iOS/MacCatalyst 26+ …
Shalini-Ashokan Feb 23, 2026
566fff2
[Testing] Feature Matrix UITest Cases for Brushes (#31833)
LogishaSelvarajSF4525 Feb 23, 2026
9dedb99
[Android] Fix Circle Stroke color is incorrectly updated as Fill colo…
NirmalKumarYuvaraj Feb 23, 2026
6886d6f
[Android] Fix TabBar FlowDirection not updating dynamically (#33091)
SubhikshaSf4851 Feb 23, 2026
445fcd6
[Android] Fix page not disposed on Shell replace navigation (#33426)
Vignesh-SF3580 Feb 23, 2026
92dc834
[Android] Fix excessive memory usage for stream and resource-based im…
Shalini-Ashokan Feb 23, 2026
c0e0d9b
[iOS/MacCatalyst] Fix CollectionView ScrollTo for horizontal layouts …
Shalini-Ashokan Feb 23, 2026
b86cba5
ContentPresenter: Propagate binding context to children with explicit…
HarishwaranVijayakumar Feb 23, 2026
a66efa2
[Android] Fix for Resize method returns an image that has already bee…
SyedAbdulAzeemSF4852 Feb 23, 2026
f282ff5
[iOS, Mac] Fix for CursorPosition not updating when typing into Entry…
SyedAbdulAzeemSF4852 Feb 23, 2026
985551b
[iOS & Mac] Fixed IndicatorView Size doesnt update dynamically (#31129)
SubhikshaSf4851 Feb 23, 2026
7f9f536
[iOS] Fix SwipeView stays open on iOS after updating content (#31248)
devanathan-vaithiyanathan Feb 23, 2026
377a4a1
[Android] Fixed Shell flyout does not disable scrolling when FlyoutVe…
NanthiniMahalingam Feb 24, 2026
6b681a7
[Testing] Feature Matrix UITest Cases for BindableLayout (#33108)
LogishaSelvarajSF4525 Feb 24, 2026
8634e1d
[Android] Add UI tests for Material 3 CheckBox (#34126)
HarishwaranVijayakumar Feb 24, 2026
ad9b09a
Fix ContentPage memory leak on Android when using NavigationPage moda…
brunck Feb 24, 2026
cd0bc47
Clarify MA003 error message (#34067)
jeremy-visionaid Feb 24, 2026
6d8bfc8
Fix: Throw a clear error when an SVG lacks dimensions instead of a Nu…
Shalini-Ashokan Feb 24, 2026
3014914
[Android] Fix for CollectionView Scrolled event is triggered on the i…
BagavathiPerumal Feb 24, 2026
7f6db9c
[Android] Fix NavigationBar overlapping StatusBar when NavigationBar …
Vignesh-SF3580 Feb 24, 2026
3d0469e
Fix for NavigationPage.TitleView does not expand with host window in …
SuthiYuvaraj Feb 24, 2026
aa174b5
[Testing] Feature Matrix UITest Cases for Shell Tabbed Page (#33159)
NafeelaNazhir Feb 24, 2026
9bc78e2
[Android] Fix for ToolbarItem retaining the icon from the previous pa…
BagavathiPerumal Feb 24, 2026
2e79d00
Fixed Label Span font property inheritance when applied via Style (#…
SubhikshaSf4851 Feb 24, 2026
ab215d0
[iOS, Android] Fix for CollectionView IsEnabled=false allows touch in…
praveenkumarkarunanithi Feb 24, 2026
81dbe0e
Fix for unable to open task using keyboard navigation on windows plat…
SuthiYuvaraj Feb 25, 2026
25dd365
[Android] Implement material3 support for TimePicker (#33646)
HarishwaranVijayakumar Feb 26, 2026
adfa470
[Android] Fix WebView in a grid expands beyond it's cell (#32145)
devanathan-vaithiyanathan Feb 26, 2026
1cf83b9
[iOS] Fix: invoke MediaPicker completion handler after DismissViewCon…
yuriikyry4enko Feb 26, 2026
ad51bb6
[Android] Fix DatePicker MinimumDate/MaximumDate not updating dynamic…
HarishwaranVijayakumar Feb 27, 2026
f118ecc
Fix crash when closing Windows based app when using TitleBar (#34032)
MFinkBK Feb 27, 2026
1f0bc7d
[Android] Implemented material3 support for Button (#33173)
Dhivya-SF4094 Feb 27, 2026
4320975
[Android] Implemented material3 support for RadioButton (#33468)
SyedAbdulAzeemSF4852 Feb 27, 2026
3a8ff02
[Android] Implemented Material3 support for Picker (#33668)
SyedAbdulAzeemSF4852 Feb 28, 2026
6832883
[Android] Implemented material3 support for Editor (#33478)
SyedAbdulAzeemSF4852 Feb 28, 2026
c60fccb
[Android] Implemented material3 support for Label (#33599)
SyedAbdulAzeemSF4852 Mar 1, 2026
6e1f847
Android drawable perf (#31567)
albyrock87 Mar 2, 2026
ee3b9ad
[iOS] Fix VerticalOffset Update When Modifying CollectionView.ItemsSo…
devanathan-vaithiyanathan Mar 2, 2026
3f9a1dd
[Revert] ContentPresenter: Propagate binding context to children with…
Ahamed-Ali Mar 4, 2026
2c73f63
[Testing] Fixed Test case failure in PR 34294 - [03/2/2026] Candidate…
TamilarasanSF4853 Mar 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -8028,14 +8028,12 @@ Methods:
void Microsoft.Maui.PlatformDispatcher:.cctor ()
void Microsoft.Maui.PlatformDispatcher:.ctor (intptr,Android.Runtime.JniHandleOwnership)
void Microsoft.Maui.PlatformInterop:.cctor ()
void Microsoft.Maui.PlatformInterop:DrawMauiDrawablePath (Android.Graphics.Drawables.PaintDrawable,Android.Graphics.Canvas,int,int,Android.Graphics.Path,Android.Graphics.Paint)
void Microsoft.Maui.PlatformInterop:LoadImageFromFont (Android.Content.Context,int,string,Android.Graphics.Typeface,single,Microsoft.Maui.IImageLoaderCallback)
void Microsoft.Maui.PlatformInterop:LoadImageFromFont (Android.Widget.ImageView,int,string,Android.Graphics.Typeface,single,Microsoft.Maui.IImageLoaderCallback)
void Microsoft.Maui.PlatformInterop:RemoveFromParent (Android.Views.View)
void Microsoft.Maui.PlatformInterop:RequestLayoutIfNeeded (Android.Views.View)
void Microsoft.Maui.PlatformInterop:Set (Android.Views.View,int,int,int,int,bool,single,single,single,single,single,single,single,single,single,single)
void Microsoft.Maui.PlatformInterop:SetColorFilter (Android.Graphics.Drawables.Drawable,int,int)
void Microsoft.Maui.PlatformInterop:SetPaintValues (Android.Graphics.Paint,single,Android.Graphics.Paint/Join,Android.Graphics.Paint/Cap,single,Android.Graphics.PathEffect)
void Microsoft.Maui.PlatformInterop:SetPivotXIfNeeded (Android.Views.View,single)
void Microsoft.Maui.PlatformInterop:SetPivotYIfNeeded (Android.Views.View,single)
void Microsoft.Maui.PlatformMauiAppCompatActivity:.cctor ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,24 @@ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
void LayoutChildren(bool animated)
{
var frame = Element.Bounds.ToCGRect();

// Apply safe area insets to the FlyoutPage container if UseSafeArea is enabled.
// This ensures the Flyout content (e.g., CollectionView) renders below the status bar/notch
// on iOS devices with notches (iPhone X and newer). Without this adjustment, the container
// would start at Y=0, causing content to overlap with the status bar.
// https://github.com/dotnet/maui/issues/29170
if (Element is FlyoutPage flyoutPage && flyoutPage is ISafeAreaView sav &&
!sav.IgnoreSafeArea && OperatingSystem.IsIOSVersionAtLeast(11))
{
var safeAreaTopInset = View.SafeAreaInsets.Top;

if (safeAreaTopInset > 0)
{
frame.Y = safeAreaTopInset;
frame.Height -= safeAreaTopInset;
}
}

var flyoutFrame = frame;
nfloat opacity = 1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,17 @@ void UpdateBarTextColor()
NavigationBar.TintColor = iconColor == null || NavPage.OnThisPlatform().GetStatusBarTextColorMode() == StatusBarTextColorMode.DoNotAdjust
? UINavigationBar.Appearance.TintColor
: iconColor.ToPlatform();

if ((OperatingSystem.IsIOSVersionAtLeast(26) || OperatingSystem.IsMacCatalystVersionAtLeast(26)) && NavigationBar.TintColor is not null)
{
if (VisibleViewController?.NavigationItem?.RightBarButtonItems is UIBarButtonItem[] items)
{
foreach (var item in items)
{
item.TintColor = NavigationBar.TintColor;
}
}
}
}

void SetStatusBarStyle()
Expand Down Expand Up @@ -1064,7 +1075,7 @@ internal static void SetFlyoutLeftBarButton(UIViewController containerController
// We only check height because the navigation bar constrains vertical space (44pt height),
// but allows horizontal flexibility. Width can vary based on icon design and content,
// while height must fit within the fixed navigation bar bounds to avoid clipping.

// if the image is bigger than the default available size, resize it
if (icon is not null)
{
Expand Down Expand Up @@ -1602,12 +1613,28 @@ UIImage GetEmptyBackIndicatorImage()
return empty;
}

/// <summary>
/// Called when the view controller's view transitions to a new size.
/// On iPad iOS 26+, manually updates TitleView frame to handle Stage Manager window resizing.
/// </summary>
public override void ViewWillTransitionToSize(SizeF toSize, IUIViewControllerTransitionCoordinator coordinator)
{
base.ViewWillTransitionToSize(toSize, coordinator);

if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad)
{
UpdateLeftBarButtonItem();

// For iOS 26+, force TitleView to re-layout on window size changes (iPad Stage Manager, multitasking)
// Complements TraitCollectionDidChange handling (device rotation) added in #32815
if (OperatingSystem.IsIOSVersionAtLeast(26) || OperatingSystem.IsMacCatalystVersionAtLeast(26))
{
coordinator.AnimateAlongsideTransition(_ =>
{
UpdateTitleViewFrameForOrientation();
}, null);
}
}
}

public override void TraitCollectionDidChange(UITraitCollection previousTraitCollection)
Expand Down Expand Up @@ -1937,6 +1964,14 @@ void UpdateToolbarItems()
}

NavigationItem.SetRightBarButtonItems(primaries is null ? [] : primaries.ToArray(), false);
if ((OperatingSystem.IsIOSVersionAtLeast(26) || OperatingSystem.IsMacCatalystVersionAtLeast(26)) && primaries is not null && _navigation.TryGetTarget(out NavigationRenderer navigationRenderer)
&& navigationRenderer.NavigationBar?.TintColor is UIColor tintColor)
{
foreach (var item in primaries)
{
item.TintColor = tintColor;
}
}

if (_navigation.TryGetTarget(out NavigationRenderer n))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,21 @@ void Destroy()
_shellPageContainer = null;
}

internal void DisposePage()
{
if (_destroyed)
{
return;
}
Destroy();

if (_page is not null)
{
_page.DisconnectHandlers();
_page = null;
}
}

protected override void Dispose(bool disposing)
{
if (_disposed)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@ public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int

var container = new ContainerView(parent.Context, content, MauiContext);
container.MatchWidth = true;

// In Auto or Disabled scroll modes, RecyclerView passes an EXACTLY heightMeasureSpec,
// causing items to be measured to the full RecyclerView height.
// Setting MeasureHeight = true forces UNSPECIFIED mode, allowing items to use their natural height (~48dp).
// This enables RecyclerView to detect when scrolling is needed and to create all required view holders.
if (_shellContext.Shell.FlyoutVerticalScrollMode != ScrollMode.Enabled)
{
container.MeasureHeight = true;
}

container.LayoutParameters = new LP(LP.MatchParent, LP.WrapContent);
linearLayout.AddView(container);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,15 @@ void AddFlyoutContentToLayoutIfNeeded(FlyoutBehavior behavior)

protected virtual void OnShellPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (_flyoutContent == null)
if (e.PropertyName == Shell.FlowDirectionProperty.PropertyName)
{
UpdateFlowDirection();
}

if (_flyoutContent is null)
{
return;
}

if (e.PropertyName == Shell.FlyoutIsPresentedProperty.PropertyName)
{
Expand All @@ -275,10 +282,6 @@ protected virtual void OnShellPropertyChanged(object sender, PropertyChangedEven

UpdateDrawerState();
}
else if (e.PropertyName == Shell.FlowDirectionProperty.PropertyName)
{
UpdateFlowDirection();
}
}

void UpdateDrawerState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ protected virtual void UpdateFlyoutContent()

_rootView.AddView(_flyoutContentView, index);
UpdateContentPadding();
UpdateVerticalScrollMode();
}


Expand Down Expand Up @@ -932,7 +933,6 @@ public RecyclerViewContainer(Context context) : base(context)
{
SetClipToPadding(false);
SetLayoutManager(_layoutManager = new ScrollLayoutManager(context, (int)Orientation.Vertical, false));
SetLayoutManager(new LinearLayoutManager(context, (int)Orientation.Vertical, false));
}

protected override void Dispose(bool disposing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ protected virtual Task<bool> HandleFragmentUpdate(ShellNavigationSource navSourc
if (ChildFragmentManager.Contains(removeFragment.Fragment) && !isForCurrentTab && removeFragment != _currentFragment)
RemoveFragment(removeFragment.Fragment);
_fragmentMap.Remove(page);

if (removeFragment is ShellContentFragment shellFragment)
{
shellFragment.DisposePage();
}
}

if (!isForCurrentTab && removeFragment != _currentFragment)
Expand Down
17 changes: 17 additions & 0 deletions src/Controls/src/Core/Editor/Editor.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,22 @@ public static void MapText(IEditorHandler handler, Editor editor)

Platform.EditTextExtensions.UpdateText(handler.PlatformView, editor);
}

// TODO: Material3 - make it public in .net 11
internal static void MapText(EditorHandler2 handler, Editor editor)
{
if (handler.PlatformView is null)
{
return;
}

if (handler.DataFlowDirection == DataFlowDirection.FromPlatform)
{
Platform.EditTextExtensions.UpdateTextFromPlatform(handler.PlatformView, editor);
return;
}

Platform.EditTextExtensions.UpdateText(handler.PlatformView, editor);
}
}
}
10 changes: 10 additions & 0 deletions src/Controls/src/Core/Editor/Editor.Mapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ public partial class Editor
EditorHandler.Mapper.ReplaceMapping<Editor, IEditorHandler>(nameof(Text), MapText);
EditorHandler.Mapper.ReplaceMapping<Editor, IEditorHandler>(nameof(TextTransform), MapText);

#if ANDROID
if (RuntimeFeature.IsMaterial3Enabled)
{
EditorHandler2.Mapper.ReplaceMapping<Editor, EditorHandler2>(nameof(Text), MapText);
EditorHandler2.Mapper.ReplaceMapping<Editor, EditorHandler2>(nameof(TextTransform), MapText);
EditorHandler2.Mapper.AppendToMapping<Editor, EditorHandler2>(nameof(VisualElement.IsFocused), InputView.MapIsFocused);
EditorHandler2.CommandMapper.PrependToMapping<Editor, EditorHandler2>(nameof(IEditor.Focus), InputView.MapFocus);
}
#endif

#if IOS || ANDROID
EditorHandler.Mapper.AppendToMapping(nameof(VisualElement.IsFocused), InputView.MapIsFocused);
EditorHandler.Mapper.AppendToMapping(nameof(VisualElement.IsVisible), InputView.MapIsVisible);
Expand Down
6 changes: 6 additions & 0 deletions src/Controls/src/Core/FlyoutPage/FlyoutPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,12 @@ void OnWindowChanged(object sender, EventArgs e)
void OnMainDisplayInfoChanged(object sender, DisplayInfoChangedEventArgs e)
{
Handler?.UpdateValue(nameof(FlyoutBehavior));

#if ANDROID || WINDOWS
// Trigger toolbar re-evaluation on orientation change. iOS handles this natively
// via PhoneFlyoutPageRenderer.ViewWillTransitionToSize().
OnPropertyChanged(nameof(FlyoutLayoutBehavior));
#endif
}

IView IFlyoutView.Flyout => this.Flyout;
Expand Down
15 changes: 15 additions & 0 deletions src/Controls/src/Core/FontExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,20 @@ public static Font ToFont(this IFontElement element, double? defaultSize = null)

return Font.OfSize(element.FontFamily, size, enableScaling: element.FontAutoScalingEnabled).WithAttributes(element.FontAttributes);
}

internal static Font GetEffectiveFont(this Span span, double defaultFontSize, Font? defaultFont)
{
var fontFamily = span.IsSet(Span.FontFamilyProperty) ? span.FontFamily : defaultFont?.Family;
var fontSize = span.IsSet(Span.FontSizeProperty) ? span.FontSize : defaultFontSize;
var fontAttributes = span.IsSet(Span.FontAttributesProperty)
? span.FontAttributes
: (defaultFont?.GetFontAttributes() ?? FontAttributes.None);
var autoScaling = span.IsSet(Span.FontAutoScalingEnabledProperty)
? span.FontAutoScalingEnabled
: (defaultFont?.AutoScalingEnabled ?? true);

return Font.OfSize(fontFamily, fontSize, enableScaling: autoScaling)
.WithAttributes(fontAttributes);
}
}
}
22 changes: 22 additions & 0 deletions src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,28 @@ protected virtual void LayoutPropertyChanged(object sender, PropertyChangedEvent
}
}

public override bool OnTouchEvent(MotionEvent e)
{
// If ItemsView is disabled, don't handle touch events
if (ItemsView?.IsEnabled == false)
{
return false;
}

return base.OnTouchEvent(e);
}

public override bool OnInterceptTouchEvent(MotionEvent e)
{
// If ItemsView is disabled, intercept all touch events to prevent interactions
if (ItemsView?.IsEnabled == false)
{
return true;
}

return base.OnInterceptTouchEvent(e);
}
Comment on lines +527 to +547

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

OnInterceptTouchEvent returns true when disabled (intercepts), but OnTouchEvent returns false (doesn't handle). This combination can lead to inconsistent/undefined touch dispatch (e.g., event intercepted from children but not consumed). If the intent is to block interaction, prefer consuming touches when disabled (typically return true from OnTouchEvent as well), or avoid intercepting altogether.

Copilot uses AI. Check for mistakes.

protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class RecyclerViewScrollListener<TItemsView, TItemsViewSource> : Recycler
int _horizontalOffset, _verticalOffset;
TItemsView _itemsView;
readonly bool _getCenteredItemOnXAndY = false;
bool _hasCompletedFirstLayout = false;

public RecyclerViewScrollListener(TItemsView itemsView, ItemsViewAdapter<TItemsView, TItemsViewSource> itemsViewAdapter) : this(itemsView, itemsViewAdapter, false)
{
Expand All @@ -28,6 +29,8 @@ public RecyclerViewScrollListener(TItemsView itemsView, ItemsViewAdapter<TItemsV
internal void UpdateAdapter(ItemsViewAdapter<TItemsView, TItemsViewSource> itemsViewAdapter)
{
ItemsViewAdapter = itemsViewAdapter;
// Reset flag when adapter changes to handle ItemsSource updates
_hasCompletedFirstLayout = false;
}

public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
Expand All @@ -38,6 +41,17 @@ public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
_horizontalOffset = itemCount == 0 ? 0 : _horizontalOffset + dx;
_verticalOffset = itemCount == 0 ? 0 : _verticalOffset + dy;

// Prevent the Scrolled event from firing on the very first layout callback only.
// This is the initial OnScrolled(0,0) call when the view is first laid out.
// After that, layout is marked as complete and all subsequent scroll events are allowed.
if (!_hasCompletedFirstLayout && !recyclerView.IsLaidOut && dx == 0 && dy == 0)
{
return;
}

// Mark that first layout has been processed - all future scrolls should fire events
_hasCompletedFirstLayout = true;

var (First, Center, Last) = GetVisibleItemsIndex(recyclerView);
var itemsViewScrolledEventArgs = new ItemsViewScrolledEventArgs
{
Expand All @@ -54,21 +68,30 @@ public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)

// Don't send RemainingItemsThresholdReached event for non-linear layout managers
// This can also happen if a layout pass has not happened yet
if (Last == -1)
if (Last == -1 || ItemsViewAdapter is null || _itemsView.RemainingItemsThreshold == -1)
{
return;
}

var itemsSource = ItemsViewAdapter.ItemsSource;
int headerValue = itemsSource.HasHeader ? 1 : 0;
int footerValue = itemsSource.HasFooter ? 1 : 0;

// Calculate actual data item count (excluding header and footer positions)
int actualItemCount = ItemsViewAdapter.ItemCount - footerValue - headerValue;

// Ensure we're within the data items region (not in header/footer)
if (Last < headerValue || Last > actualItemCount)
{
return;
}

// Check if we're at or within threshold distance from the last data item
bool isThresholdReached = (Last == actualItemCount - 1) || (actualItemCount - 1 - Last <= _itemsView.RemainingItemsThreshold);

switch (_itemsView.RemainingItemsThreshold)
if (isThresholdReached)
{
case -1:
return;
case 0:
if (Last == ItemsViewAdapter.ItemsSource.Count - 1)
_itemsView.SendRemainingItemsThresholdReached();
break;
default:
if (ItemsViewAdapter.ItemsSource.Count - 1 - Last <= _itemsView.RemainingItemsThreshold)
_itemsView.SendRemainingItemsThresholdReached();
break;
_itemsView.SendRemainingItemsThresholdReached();
}
Comment on lines +76 to 95

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

Last is an adapter position (includes header), but actualItemCount - 1 is a data-index. When a header is present, the threshold calculation becomes off-by-one (or more) and may fire early/late. Fix by translating Last into a data index (e.g., lastDataIndex = Last - headerValue) and comparing against actualItemCount - 1; also adjust the bounds check to use adapter positions consistently (e.g., ensure Last < headerValue + actualItemCount).

Copilot uses AI. Check for mistakes.
}

Expand Down
Loading
Loading