Skip to content
Open
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c6b2f10
Do not include the JS as Content (#32783)
mattleibow Nov 20, 2025
a5aba99
Update Syncfusion.Maui.Toolkit to version 1.0.8
PaulAndersonS Nov 21, 2025
749c9b5
Add null check in ControlsModalWrapper.ViewDidLayoutSubviews to preve…
Copilot Oct 4, 2025
dbd6c25
[X] Fix VSM inheritance via BasedOn styles
StephaneDelcroix Nov 21, 2025
0c25c62
Fix MediaPicker failing after temporary ComponentActivity is opened
kubaflo Nov 25, 2025
6c59667
Add accessibility identifier to MauiDoneAccessoryView Done button (#3…
Copilot Nov 24, 2025
82e4085
Implemented ios:Slider.UpdateOnTap (#20124)
kubaflo Jun 1, 2024
915335a
Allow gestures in Windows ContentView (#17482)
jsuarezruiz Sep 18, 2023
493ba1d
Remove Android conditional compilation in image source tests
jfversluis Nov 26, 2025
30ea48c
[iOS] Add support for large titles in Shell (#32081)
kubaflo Oct 19, 2025
9956232
Fixed Selected item color changes from lightskyblue to lightgray afte…
KarthikRajaKalaimani Nov 21, 2025
b4ae994
Fixed the ViewExtensions RotateYTo and RotateXTo with length 0 crashe…
Ahamed-Ali Jun 20, 2025
10f1a11
Map pin InfoWindowClicked event is never fired (#31062)
KarthikRajaKalaimani Aug 6, 2025
ca8ee4f
Fix NavigationPage.TitleView resizing on iOS 26+ rotation
kubaflo Nov 23, 2025
e13ef48
Fix NullReferenceException when using x:Name on resources
StephaneDelcroix Nov 27, 2025
d76f98d
[iOS] SwipeView Closes when Content Changes - right and bottom - fix
kubaflo Jun 25, 2025
f9923f9
Prevent CollectionView SelectionChanged from triggering on SwipeView …
Vignesh-SF3580 Jul 16, 2025
5e643b7
Fix iOS WebView target blank navigation event handling (#32199)
Copilot Oct 24, 2025
268ce95
[iOS] Fixed current item change on device orientation (#32672)
SubhikshaSf4851 Nov 17, 2025
d55db6e
fixed - Background and BackgroundColor behave differently in Collecti…
Vignesh-SF3580 Nov 14, 2025
3679840
[Issue-Resolver] Fix TabBar visibility on macOS 26 (Tahoe) (#32910)
kubaflo Dec 1, 2025
3e9ef97
[iOS] Fix for Unable to Update iOS SwipeGesture Direction at Runtime …
BagavathiPerumal Dec 1, 2025
caf97f2
[iOS] SearchHandler overlaps title and title view - fix (#30772)
kubaflo Dec 2, 2025
33d6210
[Windows] Fix for SemanticScreenReader.Default.Announce throws except…
HarishwaranVijayakumar Dec 2, 2025
02575cd
Fix MediaPicker and FilePicker returning null on cancellation (#32656)
Copilot Dec 2, 2025
b9f0d08
[iOS] Fixed the text color issue when setting it to null dynamically …
Ahamed-Ali Dec 2, 2025
2cd5a30
[Android] Fixed Shell Colors Do Not Update Correctly When Switching B…
NanthiniMahalingam Dec 2, 2025
32612ca
Fix for SwipeView Command Binding Issue in CollectionView Templates (…
BagavathiPerumal Dec 2, 2025
82fe0ba
Fix CollectionView header/footer not removed when set to null on Andr…
Shalini-Ashokan Dec 2, 2025
15557ed
[Testing] Additional Feature Matrix Test Cases for ScrollView (#32617)
LogishaSelvarajSF4525 Dec 2, 2025
3765898
Fix for iOS CollectionView2 ItemSizingStrategy="MeasureFirstItem" Fa…
SuthiYuvaraj Dec 2, 2025
be26faf
Fix ContentViewRespondsWhenViewRemoved test fails on Catalyst (#32481)
SuthiYuvaraj Dec 2, 2025
a99b1ca
Revert "[Issue-Resolver] Fix TabBar visibility on macOS 26 (Tahoe) (#…
jfversluis Dec 3, 2025
e86b975
Fixed HorizontalStackLayout Crashes Debugger on Negative Spacing (#26…
devanathan-vaithiyanathan Dec 3, 2025
c90f6db
Fix: Picker selects incorrect item after item removal (#29313)
Shalini-Ashokan Dec 3, 2025
4fe4309
Fixed Button rendering overflow in StackLayout (#28001)
Dhivya-SF4094 Dec 3, 2025
274fcf2
[Windows] Fixed the OneWayBinding issue with MultiBindingConverter on…
Ahamed-Ali Dec 3, 2025
6bf026c
Entry Height gets updated when loaded inside the RoundRectangle Shape…
SuthiYuvaraj Dec 3, 2025
4587ae1
Revert "Add accessibility identifier to MauiDoneAccessoryView Done bu…
jfversluis Dec 5, 2025
4f5c8c6
[Testing] Fixed Test case failure in PR 32982 - [08/12/2025] Candidat…
HarishKumarSF4517 Dec 5, 2025
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
  •  
  •  
  •  
9 changes: 9 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,15 @@
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
</PropertyGroup>

<!-- TypeScript compilation -->
<PropertyGroup>
<TypeScriptTarget>ES2020</TypeScriptTarget>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
<TypeScriptNoImplicitAny>true</TypeScriptNoImplicitAny>
<TypeScriptCompileOnSaveEnabled>true</TypeScriptCompileOnSaveEnabled>
<TypeScriptCompileBlocked Condition=" '$(TypeScriptCompileBlocked)' == '' and '$(CI)' != 'true' and '$(TF_BUILD)' != 'true' ">true</TypeScriptCompileBlocked>
</PropertyGroup>

<!-- Windows specific settings -->
<PropertyGroup Condition="'$(_MauiTargetPlatformIsWindows)' == 'True'">
<WindowsSdkPackageVersion>10.0.19041.44</WindowsSdkPackageVersion>
Expand Down
2 changes: 2 additions & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,7 @@

<!-- Tell typescript to stop deleting everything before building the next TFM -->
<Target Name="TypeScriptDeleteOutputFromOtherConfigs" />
<!-- Don't include any JS files in the Content, we will embed it -->
<Target Name="GetTypeScriptOutputForPublishing" />

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -1595,6 +1595,38 @@ public override void ViewWillTransitionToSize(SizeF toSize, IUIViewControllerTra
UpdateLeftBarButtonItem();
}

public override void TraitCollectionDidChange(UITraitCollection previousTraitCollection)
{
base.TraitCollectionDidChange(previousTraitCollection);

// Check if orientation changed (size class transition)
if (previousTraitCollection?.VerticalSizeClass != TraitCollection.VerticalSizeClass ||
previousTraitCollection?.HorizontalSizeClass != TraitCollection.HorizontalSizeClass)
{
if (OperatingSystem.IsIOSVersionAtLeast(26) || OperatingSystem.IsMacCatalystVersionAtLeast(26))
{
UpdateTitleViewFrameForOrientation();
}
}
}

/// iOS 26+ requires autoresizing masks (UIViewAutoresizing.FlexibleWidth) During orientation changes, the autoresizing mask
/// automatically adjusts the width, but we need to explicitly update the frame to ensure the
/// title view uses the full available width from the navigation bar. Without this update,
/// the title view may not properly expand to fill the navigation bar after rotation.
Comment on lines +1613 to +1616
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

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

The XML documentation comment is malformed - it's missing proper line breaks and the sentence structure is unclear. Should be formatted as proper documentation with clear sentence boundaries.

Suggested change
/// iOS 26+ requires autoresizing masks (UIViewAutoresizing.FlexibleWidth) During orientation changes, the autoresizing mask
/// automatically adjusts the width, but we need to explicitly update the frame to ensure the
/// title view uses the full available width from the navigation bar. Without this update,
/// the title view may not properly expand to fill the navigation bar after rotation.
/// <summary>
/// On iOS 26 and later, autoresizing masks (UIViewAutoresizing.FlexibleWidth) are required.
/// During orientation changes, the autoresizing mask automatically adjusts the width.
/// However, we need to explicitly update the frame to ensure the title view uses the full available width from the navigation bar.
/// Without this update, the title view may not properly expand to fill the navigation bar after rotation.
/// </summary>

Copilot uses AI. Check for mistakes.
void UpdateTitleViewFrameForOrientation()
{
if (NavigationItem?.TitleView is not UIView titleView)
return;

if (!_navigation.TryGetTarget(out NavigationRenderer navigationRenderer))
return;

var navigationBarFrame = navigationRenderer.NavigationBar.Frame;
titleView.Frame = new RectangleF(0, 0, navigationBarFrame.Width, navigationBarFrame.Height);
titleView.LayoutIfNeeded();
}

internal void UpdateLeftBarButtonItem(Page pageBeingRemoved = null)
{
NavigationRenderer n;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ protected virtual void SetAppearance(ShellAppearance appearance)

protected virtual bool ChangeSection(ShellSection shellSection)
{
// Update shell appearance based on the new shell section when switching between tabs
((IShellController)ShellContext.Shell).AppearanceChanged(shellSection, false);
return ((IShellItemController)ShellItem).ProposeSection(shellSection);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.ComponentModel;
using System.Linq;
using Foundation;
using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;
using Microsoft.Maui.Graphics;
using ObjCRuntime;
using UIKit;
Expand Down Expand Up @@ -399,6 +400,7 @@ void OnDisplayedPageChanged(Page page)
{
_displayedPage.PropertyChanged += OnDisplayedPagePropertyChanged;
UpdateTabBarHidden();
UpdateLargeTitles();
}
}

Expand All @@ -408,6 +410,31 @@ void OnDisplayedPagePropertyChanged(object sender, PropertyChangedEventArgs e)
UpdateTabBarHidden();
}


void UpdateLargeTitles()
{
var page = _displayedPage;
if (page is null || !OperatingSystem.IsIOSVersionAtLeast(11))
return;

var largeTitleDisplayMode = page.OnThisPlatform().LargeTitleDisplay();

if (SelectedViewController is UINavigationController navigationController)
{
navigationController.NavigationBar.PrefersLargeTitles = largeTitleDisplayMode == LargeTitleDisplayMode.Always;
var top = navigationController.TopViewController;
if (top is not null)
{
top.NavigationItem.LargeTitleDisplayMode = largeTitleDisplayMode switch
{
LargeTitleDisplayMode.Always => UINavigationItemLargeTitleDisplayMode.Always,
LargeTitleDisplayMode.Automatic => UINavigationItemLargeTitleDisplayMode.Automatic,
_ => UINavigationItemLargeTitleDisplayMode.Never
};
}
}
}

void RemoveRenderer(IShellSectionRenderer renderer)
{
if (_sectionRenderers.Remove(renderer.ViewController))
Expand Down Expand Up @@ -441,6 +468,7 @@ IShellSectionRenderer RendererForViewController(UIViewController viewController)
public override void ViewWillLayoutSubviews()
{
UpdateTabBarHidden();
UpdateLargeTitles();
base.ViewWillLayoutSubviews();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,7 @@ void AttachSearchController()
});

searchBar.BookmarkButtonClicked += BookmarkButtonClicked;
searchBar.OnEditingStopped += OnSearchBarEditingStopped;

searchBar.Placeholder = SearchHandler.Placeholder;
UpdateSearchIsEnabled(_searchController);
Expand Down Expand Up @@ -985,6 +986,14 @@ void AttachSearchController()
UpdateAutomationId();
}

void OnSearchBarEditingStopped(object? sender, EventArgs e)
{
if (_searchController is not null)
{
_searchController.Active = false;
}
}

void BookmarkButtonClicked(object? sender, EventArgs e)
{
(SearchHandler as ISearchHandlerController)?.ClearPlaceholderClicked();
Expand All @@ -995,6 +1004,11 @@ void DettachSearchController()

_searchHandlerAppearanceTracker?.Dispose();
_searchHandlerAppearanceTracker = null;
if (_searchController?.SearchBar is UISearchBar searchBar)
{
searchBar.BookmarkButtonClicked -= BookmarkButtonClicked;
searchBar.OnEditingStopped -= OnSearchBarEditingStopped;
}

if (NavigationItem is not null)
{
Expand Down
5 changes: 1 addition & 4 deletions src/Controls/src/Core/GradientStop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ public override bool Equals(object obj)
}

/// <include file="../../docs/Microsoft.Maui.Controls/GradientStop.xml" path="//Member[@MemberName='GetHashCode']/Docs/*" />
public override int GetHashCode()
{
return -1234567890 + (Color?.GetHashCode() ?? 0);
}
public override int GetHashCode() => base.GetHashCode();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ protected override void ItemsViewPropertyChanged(object sender, PropertyChangedE
{
base.ItemsViewPropertyChanged(sender, property);

if (property.Is(Microsoft.Maui.Controls.StructuredItemsView.HeaderProperty))
if (property.Is(Microsoft.Maui.Controls.StructuredItemsView.HeaderProperty) || property.Is(Microsoft.Maui.Controls.StructuredItemsView.HeaderTemplateProperty))
{
UpdateHasHeader();
NotifyDataSetChanged();
}
else if (property.Is(Microsoft.Maui.Controls.StructuredItemsView.FooterProperty))
else if (property.Is(Microsoft.Maui.Controls.StructuredItemsView.FooterProperty) || property.Is(Microsoft.Maui.Controls.StructuredItemsView.FooterTemplateProperty))
{
UpdateHasFooter();
NotifyDataSetChanged();
Expand Down
28 changes: 28 additions & 0 deletions src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,34 @@ internal void UpdateEmptyViewVisibility()
SwapAdapter(ItemsViewAdapter, true);
UpdateLayoutManager();
}
else if (showEmptyView && currentAdapter == _emptyViewAdapter)
{
if (ShouldUpdateEmptyView())
{
// Header/footer properties changed - detach and reattach adapter to force RecyclerView to recalculate the positions.
SetAdapter(null);
SwapAdapter(_emptyViewAdapter, true);
UpdateEmptyView();
}
}
}

bool ShouldUpdateEmptyView()
{
if (ItemsView is StructuredItemsView structuredItemsView)
{
if (_emptyViewAdapter.Header != structuredItemsView.Header ||
_emptyViewAdapter.HeaderTemplate != structuredItemsView.HeaderTemplate ||
_emptyViewAdapter.Footer != structuredItemsView.Footer ||
_emptyViewAdapter.FooterTemplate != structuredItemsView.FooterTemplate ||
_emptyViewAdapter.EmptyView != ItemsView.EmptyView ||
_emptyViewAdapter.EmptyViewTemplate != ItemsView.EmptyViewTemplate)
{
return true;
}
}

return false;
}

internal void AdjustScrollForItemUpdate()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ bool IsUsingVSMForSelectionColor(View view)
for (var setterIndex = 0; setterIndex < state.Setters.Count; setterIndex++)
{
var setter = state.Setters[setterIndex];
if (setter.Property.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
if (setter.Property.PropertyName == VisualElement.BackgroundColorProperty.PropertyName ||
setter.Property.PropertyName == VisualElement.BackgroundProperty.PropertyName)
{
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Controls/src/Core/Handlers/Items/iOS/TemplatedCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ bool IsUsingVSMForSelectionColor(View view)
for (var setterIndex = 0; setterIndex < state.Setters.Count; setterIndex++)
{
var setter = state.Setters[setterIndex];
if (setter.Property.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
if (setter.Property.PropertyName == VisualElement.BackgroundColorProperty.PropertyName ||
setter.Property.PropertyName == VisualElement.BackgroundProperty.PropertyName)
{
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ internal class LayoutSnapInfo

public partial class CollectionViewHandler2
{
// Cache for MeasureFirstItem optimization
CoreGraphics.CGSize _firstItemMeasuredSize = CoreGraphics.CGSize.Empty;

public CollectionViewHandler2() : base(Mapper)
{
Expand All @@ -45,6 +47,30 @@ public CollectionViewHandler2(PropertyMapper mapper = null) : base(mapper ?? Map

}

/// <summary>
/// Gets the cached first item measured size for MeasureFirstItem optimization.
/// Returns CGSize.Empty if not cached or not using MeasureFirstItem strategy.
/// </summary>
internal CoreGraphics.CGSize GetCachedFirstItemSize()
{
if (VirtualView is CollectionView cv && cv.ItemSizingStrategy == ItemSizingStrategy.MeasureFirstItem)
{
return _firstItemMeasuredSize;
}
return CoreGraphics.CGSize.Empty;
}

/// <summary>
/// Sets the cached first item measured size for MeasureFirstItem optimization.
/// </summary>
internal void SetCachedFirstItemSize(CoreGraphics.CGSize size)
{
if (VirtualView is CollectionView cv && cv.ItemSizingStrategy == ItemSizingStrategy.MeasureFirstItem)
{
_firstItemMeasuredSize = size;
}
}

public static PropertyMapper<CollectionView, CollectionViewHandler2> Mapper = new(ItemsViewMapper)
{
[ReorderableItemsView.CanReorderItemsProperty.PropertyName] = MapCanReorderItems,
Expand All @@ -56,6 +82,7 @@ public CollectionViewHandler2(PropertyMapper mapper = null) : base(mapper ?? Map
[StructuredItemsView.FooterTemplateProperty.PropertyName] = MapFooterTemplate,
[StructuredItemsView.HeaderProperty.PropertyName] = MapHeaderTemplate,
[StructuredItemsView.FooterProperty.PropertyName] = MapFooterTemplate,
[StructuredItemsView.ItemSizingStrategyProperty.PropertyName] = MapItemSizingStrategy,
[GroupableItemsView.GroupHeaderTemplateProperty.PropertyName] = MapHeaderTemplate,
[GroupableItemsView.GroupFooterTemplateProperty.PropertyName] = MapFooterTemplate,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Microsoft.Maui.Controls.Handlers.Items2
{
public class CarouselViewController2 : ItemsViewController2<CarouselView>
{
bool _isRotating = false;
bool _isUpdating = false;
int _section = 0;
CarouselViewLoopManager _carouselViewLoopManager;
Expand Down Expand Up @@ -64,6 +65,16 @@ public override void ViewDidLoad()
{
InitializeCarouselViewLoopManager();
base.ViewDidLoad();
// Subscribe to orientation change notifications
NSNotificationCenter.DefaultCenter.AddObserver(UIDevice.OrientationDidChangeNotification, DeviceOrientationChanged);
}

void DeviceOrientationChanged(NSNotification notification)
{
if (InitialPositionSet)
{
_isRotating = true;
}
}

public override void ViewWillLayoutSubviews()
Expand All @@ -77,6 +88,22 @@ public override async void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
await UpdateInitialPosition();

if (_isRotating)
{
BoundsSizeChanged();
_isRotating = false;
}
}

void BoundsSizeChanged()
{
// Re-center the current item after bounds change to ensure proper positioning
// This is especially important during device rotation to maintain the correct scroll position
if (ItemsView is CarouselView carousel && carousel.Position >= 0)
{
carousel.ScrollTo(carousel.Position, position: Microsoft.Maui.Controls.ScrollToPosition.Center, animate: false);
}
}

public override void DraggingStarted(UIScrollView scrollView)
Expand Down Expand Up @@ -150,10 +177,12 @@ void TearDown(CarouselView carouselView)
InitialPositionSet = false;

UnsubscribeCollectionItemsSourceChanged(ItemsSource);

// Clean up orientation notification observer
NSNotificationCenter.DefaultCenter.RemoveObserver(this, UIDevice.OrientationDidChangeNotification, null);
_carouselViewLoopManager?.Dispose();
_carouselViewLoopManager = null;
_isUpdating = false;
_isRotating = false;
}

internal void UpdateScrollingConstraints()
Expand Down Expand Up @@ -372,6 +401,12 @@ internal bool IsUpdating()
{
return _isUpdating;
}

internal bool IsRotating()
{
return _isRotating;
}

internal void UpdateLoop()
{
if (ItemsView is not CarouselView carousel)
Expand Down
Loading
Loading