Skip to content

Commit e863130

Browse files
authored
[2025/06/16] Candidate - In Flight Branch (#29886)
For more information about inflight process check https://github.com/dotnet/maui/wiki/Inflight-Branch-Process # .NET MAUI Release Notes - inflight/candidate Branch ## MAUI Product Fixes * [iOS] Fix SwipeView programmatic open when background color is set by @Shalini-Ashokan in #29765 * [iOS] FormattedText with text color causes stack overflow - fix by @kubaflo in #29874 * [iOS] Fix AdaptiveTrigger not working as expected by @jsuarezruiz in #20987 * [iOS] Fix for Flyout title is not broken over multiple lines when you rotate your screen by @BagavathiPerumal in #29171 * [Windows] Fix for Assigning null to the SelectedItem of the CollectionView in the SelectionChanged event does not clear the selection by @SyedAbdulAzeemSF4852 in #29288 * Fix TapCoordinates method in Catalyst by @jsuarezruiz in #29775 * Fixed ItemSpacing on CarouselView resizes items [Android] by @Dhivya-SF4094 in #29796 * Perf : ButtonContentTypeConverter now using InvariantCulture to parse double by @antoine-jonathan in #25393 * ToolbarItem behavior with ImageSource iOS - fix by @kubaflo in #28833 * [Android] Fixed Button Shadow Color Transparency Not Applied Correctly by @NanthiniMahalingam in #29371 * Don't call NSAttributedString with HTML from a background thread by @kubaflo in #26153 * [Windows] Implemented the Resize and Downsize functions in the W2DImage class by @HarishwaranVijayakumar in #29138 * Templated indicator view - improvements by @kubaflo in #25642 * Update Issue25946.xaml by @anandhan-rajagopal in #30025 ## Testing * Fixed Test case failure in PR 26153 - iOS by @kubaflo in #29906 * Fixed Test case failure in PR 25642 - snapshots by @kubaflo in #29881 * [Testing] Feature Matrix UITest Cases for RadioButton by @TamilarasanSF4853 in #29744 * [Testing] Feature Matrix UITest Cases for CollectionView ItemsSource Feature by @LogishaSelvarajSF4525 in #29322 * [Testing] Feature Matrix UITest Cases for Stepper by @nivetha-nagalingam in #29731 * [Testing] Feature Matrix UITest Cases for CheckBox Control by @anandhan-rajagopal in #29739 * Update the comment for the test properties by @mattleibow in #27306 ## Dependency Updates * No changes in this category ## Docs * No changes in this category ## Housekeeping * [create-pull-request] automated change by @github-actions[bot] in #29875 * [create-pull-request] automated change by @github-actions[bot] in #29792 * [create-pull-request] automated change by @github-actions[bot] in #29760 **Full Changelog**: origin/main...origin/inflight/candidate
2 parents 5030975 + 5e9310b commit e863130

File tree

195 files changed

+5638
-95
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

195 files changed

+5638
-95
lines changed

src/Controls/src/Core/Button/Button.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c
598598
int spacingIndex = spacingFirst ? 0 : (parts.Length == 2 ? 1 : -1);
599599

600600
if (spacingIndex > -1)
601-
spacing = double.Parse(parts[spacingIndex]);
601+
spacing = double.Parse(parts[spacingIndex], CultureInfo.InvariantCulture);
602602

603603
if (positionIndex > -1)
604604
position = (ButtonContentLayout.ImagePosition)Enum.Parse(typeof(ButtonContentLayout.ImagePosition), parts[positionIndex], true);

src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/UIContainerCell.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ internal UIContainerCell(string cellId, View view, Shell shell, object context)
3131
var platformView = view.ToPlatform();
3232
ContentView.AddSubview(platformView);
3333
platformView.AccessibilityTraits |= UIAccessibilityTrait.Button;
34+
platformView.TranslatesAutoresizingMaskIntoConstraints = false;
35+
36+
var margin = view.Margin;
37+
var constraints = new NSLayoutConstraint[]
38+
{
39+
platformView.LeadingAnchor.ConstraintEqualTo(ContentView.LeadingAnchor, (nfloat)margin.Left),
40+
platformView.TrailingAnchor.ConstraintEqualTo(ContentView.TrailingAnchor, (nfloat)(-margin.Right)),
41+
platformView.TopAnchor.ConstraintEqualTo(ContentView.TopAnchor, (nfloat)margin.Top),
42+
platformView.BottomAnchor.ConstraintEqualTo(ContentView.BottomAnchor, (nfloat)(-margin.Bottom))
43+
};
44+
NSLayoutConstraint.ActivateConstraints(constraints);
3445

3546
_renderer.PlatformView.ClipsToBounds = true;
3647
ContentView.ClipsToBounds = true;

src/Controls/src/Core/Compatibility/iOS/Extensions/ToolbarItemExtensions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ void UpdateIconAndStyle(ToolbarItem item)
112112
}
113113
item.IconImageSource.LoadImage(mauiContext, result =>
114114
{
115-
Image = result?.Value;
115+
Image = item.IconImageSource is not FontImageSource
116+
? result?.Value.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
117+
: result?.Value;
116118
Style = UIBarButtonItemStyle.Plain;
117119
});
118120
}

src/Controls/src/Core/Handlers/Items/CarouselViewHandler.Android.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ double GetItemWidth()
9595
if (double.IsInfinity(width))
9696
return width;
9797

98-
itemWidth = (int)(width - Context?.ToPixels(VirtualView.PeekAreaInsets.Left) - Context?.ToPixels(VirtualView.PeekAreaInsets.Right) - Context?.ToPixels(listItemsLayout.ItemSpacing));
98+
itemWidth = (int)(width - Context?.ToPixels(VirtualView.PeekAreaInsets.Left) - Context?.ToPixels(VirtualView.PeekAreaInsets.Right));
9999
}
100100

101101
return itemWidth;
@@ -112,7 +112,7 @@ double GetItemHeight()
112112
if (double.IsInfinity(height))
113113
return height;
114114

115-
itemHeight = (int)(height - Context?.ToPixels(VirtualView.PeekAreaInsets.Top) - Context?.ToPixels(VirtualView.PeekAreaInsets.Bottom) - Context?.ToPixels(listItemsLayout.ItemSpacing));
115+
itemHeight = (int)(height - Context?.ToPixels(VirtualView.PeekAreaInsets.Top) - Context?.ToPixels(VirtualView.PeekAreaInsets.Bottom));
116116
}
117117

118118
return itemHeight;

src/Controls/src/Core/Handlers/Items/SelectableItemsViewHandler.Windows.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ namespace Microsoft.Maui.Controls.Handlers.Items
1414
public partial class SelectableItemsViewHandler<TItemsView> : StructuredItemsViewHandler<TItemsView> where TItemsView : SelectableItemsView
1515
{
1616
bool _ignorePlatformSelectionChange;
17+
bool _ignoreVirtualSelectionChange;
1718

1819
protected override void ConnectHandler(ListViewBase platformView)
1920
{
@@ -132,6 +133,13 @@ void UpdatePlatformSelection()
132133

133134
void VirtualSelectionChanged(object sender, SelectionChangedEventArgs e)
134135
{
136+
// When the selection changes within the SelectionChanged event, the new selection isn't immediately reflected in the view.
137+
// After the virtual selection is correctly updated, the flag is reset to enable future updates
138+
if (_ignoreVirtualSelectionChange)
139+
{
140+
_ignoreVirtualSelectionChange = false;
141+
return;
142+
}
135143
UpdatePlatformSelection();
136144
}
137145

@@ -172,10 +180,10 @@ void UpdateVirtualSingleSelection()
172180

173181
if (ItemsView != null)
174182
{
175-
ItemsView.SelectionChanged -= VirtualSelectionChanged;
183+
_ignoreVirtualSelectionChange = true;
176184
ItemsView.SelectedItem = selectedItem;
177185

178-
ItemsView.SelectionChanged += VirtualSelectionChanged;
186+
_ignoreVirtualSelectionChange = false;
179187
}
180188
}
181189

src/Controls/src/Core/IndicatorView/IndicatorStackLayout.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,19 +98,30 @@ internal void ResetIndicatorCount(int oldCount)
9898
}
9999
}
100100

101+
protected override void OnInsert(int index, IView view)
102+
{
103+
base.OnInsert(index, view);
104+
ResetIndicatorStylesNonBatch();
105+
}
106+
107+
protected override void OnRemove(int index, IView view)
108+
{
109+
base.OnRemove(index, view);
110+
ResetIndicatorStylesNonBatch();
111+
}
112+
101113
void ResetIndicatorStylesNonBatch()
102114
{
103115
var indicatorCount = _indicatorView.Count;
104116
var childrenCount = Children.Count;
117+
var maxVisible = _indicatorView.MaximumVisible;
118+
var position = _indicatorView.Position;
119+
var selectedIndex = position >= maxVisible ? maxVisible - 1 : position;
105120

106121
for (int index = 0; index < childrenCount; index++)
107122
{
108-
var maxVisible = _indicatorView.MaximumVisible;
109-
var position = _indicatorView.Position;
110-
var selectedIndex = position >= maxVisible ? maxVisible - 1 : position;
111123
bool isSelected = index == selectedIndex;
112-
var visualElement = Children[index] as VisualElement;
113-
if (visualElement is null)
124+
if (Children[index] is not VisualElement visualElement)
114125
{
115126
return;
116127
}

src/Controls/src/Core/Label/Label.iOS.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,17 @@ public static void MapMaxLines(ILabelHandler handler, Label label)
3636
handler.PlatformView?.UpdateMaxLines(label);
3737
}
3838

39-
static void MapFormatting(ILabelHandler handler, Label label)
39+
internal static void MapFormatting(ILabelHandler handler, Label label)
4040
{
41-
// we need to re-apply color and font for HTML labels
42-
if (!label.HasFormattedTextSpans && label.TextType == TextType.Html)
41+
if (IsPlainText(label))
42+
{
43+
LabelHandler.MapFormatting(handler, label);
44+
}
45+
else if (!label.HasFormattedTextSpans && label.TextType == TextType.Html) // we need to re-apply color and font for HTML labels
4346
{
4447
handler.UpdateValue(nameof(ILabel.TextColor));
4548
handler.UpdateValue(nameof(ILabel.Font));
4649
}
47-
48-
if (!IsPlainText(label))
49-
return;
50-
51-
LabelHandler.MapFormatting(handler, label);
5250
}
5351

5452
void RecalculateSpanPositions(Size size)

src/Controls/src/Core/Platform/iOS/Extensions/LabelExtensions.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,22 @@ public static void UpdateText(this UILabel platformLabel, Label label)
1414
switch (label.TextType)
1515
{
1616
case TextType.Html:
17-
platformLabel.UpdateTextHtml(label);
17+
// NOTE: Setting HTML text this will crash with some sort of consistency error.
18+
// https://github.com/dotnet/maui/issues/25946
19+
// Here we have to dispatch back the the main queue to avoid the crash.
20+
// This is observed with CarouselView 1 but not with 2, so hopefully this
21+
// will be just disappear once we switch.
22+
CoreFoundation.DispatchQueue.MainQueue.DispatchAsync(() =>
23+
{
24+
platformLabel.UpdateTextHtml(label);
25+
26+
if (label.Handler is LabelHandler labelHandler)
27+
Label.MapFormatting(labelHandler, label);
28+
29+
// NOTE: Because we are updating text outside the normal layout
30+
// pass, we need to invalidate the measure for the next pass.
31+
label.InvalidateMeasure();
32+
});
1833
break;
1934

2035
default:

src/Controls/tests/DeviceTests/Elements/Label/LabelTests.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,10 @@ await AttachAndRun(layout, async (handler) =>
333333

334334
label.TextType = TextType.Html;
335335

336+
// We need to delay here because platformLabel.UpdateTextHtml(label) and label.InvalidateMeasure()
337+
// are dispatched asynchronously to the main thread and may not complete immediately.
338+
// https://github.com/dotnet/maui/pull/26153
339+
await Task.Delay(100);
336340
await platformView.AssertDoesNotContainColor(Colors.Red, MauiContext);
337341
});
338342
}
@@ -517,9 +521,13 @@ public async Task FontStuffAppliesEvenInHtmlMode()
517521
Text = "<p>Test</p>"
518522
};
519523

520-
await InvokeOnMainThreadAsync(() =>
524+
await InvokeOnMainThreadAsync(async () =>
521525
{
522526
var handler = CreateHandler<LabelHandler>(label);
527+
// We need to delay here because platformLabel.UpdateTextHtml(label) and label.InvalidateMeasure()
528+
// are dispatched asynchronously to the main thread and may not complete immediately.
529+
// https://github.com/dotnet/maui/pull/26153
530+
await Task.Delay(100);
523531
AssertEquivalentFont(handler, label.ToFont());
524532
});
525533
}
@@ -715,9 +723,13 @@ public async Task FontStuffAfterTextTypeIsCorrect()
715723
Text = "<p>Test</p>"
716724
};
717725

718-
await InvokeOnMainThreadAsync(() =>
726+
await InvokeOnMainThreadAsync(async () =>
719727
{
720728
var handler = CreateHandler<LabelHandler>(label);
729+
// We need to delay here because platformLabel.UpdateTextHtml(label) and label.InvalidateMeasure()
730+
// are dispatched asynchronously to the main thread and may not complete immediately.
731+
// https://github.com/dotnet/maui/pull/26153
732+
await Task.Delay(100);
721733
label.FontFamily = "Baskerville";
722734
label.FontSize = 64;
723735
AssertEquivalentFont(handler, label.ToFont());

0 commit comments

Comments
 (0)