Skip to content

Commit 98a62a2

Browse files
authored
[2025/05/26] Candidate - In Flight Branch (#29623)
For more information about inflight process check https://github.com/dotnet/maui/wiki/Inflight-Branch-Process
2 parents 6b41f4f + 9877ebc commit 98a62a2

File tree

124 files changed

+4387
-221
lines changed

Some content is hidden

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

124 files changed

+4387
-221
lines changed

src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarTracker.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public Color TintColor
136136
_tintColor = value;
137137
if (Page != null)
138138
{
139-
UpdateToolbarItems();
139+
UpdateToolbarItemsTintColors();
140140
UpdateLeftBarButtonItem();
141141
}
142142
}
@@ -628,9 +628,21 @@ protected virtual void UpdateTitleView(Context context, AToolbar toolbar, View t
628628
_toolbar.Handler?.UpdateValue(nameof(Toolbar.TitleView));
629629
}
630630

631+
private void UpdateToolbarItemsTintColors(AToolbar toolbar)
632+
{
633+
var menu = toolbar.Menu;
634+
int _placeholderMenuItemId = 100;
635+
if (menu.FindItem(_placeholderMenuItemId) is IMenuItem item)
636+
{
637+
using (var icon = item.Icon)
638+
icon.SetColorFilter(TintColor.ToPlatform(Colors.White), FilterMode.SrcAtop);
639+
}
640+
}
641+
631642
protected virtual void UpdateToolbarItems(AToolbar toolbar, Page page)
632643
{
633644
var menu = toolbar.Menu;
645+
int _placeholderMenuItemId = 100;
634646
SearchHandler = Shell.GetSearchHandler(page);
635647
if (SearchHandler != null && SearchHandler.SearchBoxVisibility != SearchBoxVisibility.Hidden)
636648
{
@@ -650,7 +662,7 @@ protected virtual void UpdateToolbarItems(AToolbar toolbar, Page page)
650662
if (SearchHandler.SearchBoxVisibility == SearchBoxVisibility.Collapsible)
651663
{
652664
var placeholder = new Java.Lang.String(SearchHandler.Placeholder);
653-
var item = menu.Add(placeholder);
665+
var item = menu.Add(0, _placeholderMenuItemId, 0, placeholder);
654666
placeholder.Dispose();
655667

656668
item.SetEnabled(SearchHandler.IsSearchEnabled);
@@ -725,6 +737,11 @@ void UpdateToolbarItems()
725737
UpdateToolbarItems(_platformToolbar, Page);
726738
}
727739

740+
void UpdateToolbarItemsTintColors()
741+
{
742+
UpdateToolbarItemsTintColors(_platformToolbar);
743+
}
744+
728745
class FlyoutIconDrawerDrawable : DrawerArrowDrawable
729746
{
730747
public Drawable IconBitmap { get; set; }

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,10 @@ void UpdateSearchBarBackgroundColor(UITextField textField)
177177
backgroundView.ClipsToBounds = true;
178178
if (_defaultBackgroundColor == null)
179179
_defaultBackgroundColor = backgroundView.BackgroundColor;
180-
backgroundView.BackgroundColor = backGroundColor.ToPlatform();
180+
181+
UIColor backgroundColor = backGroundColor.ToPlatform();
182+
backgroundView.BackgroundColor = backgroundColor;
183+
textField.BackgroundColor = backgroundColor;
181184
}
182185

183186
void UpdateCancelButtonColor(UIButton cancelButton)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ protected override void UpdateItemTemplate()
8787
return;
8888

8989
ListViewBase.ItemTemplate = CarouselItemsViewTemplate;
90+
UpdateItemsSource();
9091
}
9192

9293
protected override void OnScrollViewerFound(ScrollViewer scrollViewer)

src/Controls/src/Core/Handlers/Items/iOS/ReorderableItemsViewController.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ public class ReorderableItemsViewController<TItemsView> : GroupableItemsViewCont
1414
bool _disposed;
1515
UILongPressGestureRecognizer _longPressGestureRecognizer;
1616

17+
#if MACCATALYST
18+
const double defaultMacCatalystPressDuration = 0.1;
19+
#endif
20+
1721
public ReorderableItemsViewController(TItemsView reorderableItemsView, ItemsViewLayout layout)
1822
: base(reorderableItemsView, layout)
1923
{
@@ -162,6 +166,12 @@ public void UpdateCanReorderItems()
162166
if (_longPressGestureRecognizer == null)
163167
{
164168
_longPressGestureRecognizer = new UILongPressGestureRecognizer(HandleLongPress);
169+
#if MACCATALYST
170+
// On Mac Catalyst, we disable the default drag interaction and instead handle dragging using a long press gesture recognizer.
171+
// Since a long press typically takes more time to trigger than the system's default drag interaction,
172+
// we reduce the minimum press duration to 0.1 seconds to better match the previous behavior.
173+
_longPressGestureRecognizer.MinimumPressDuration = defaultMacCatalystPressDuration;
174+
#endif
165175
CollectionView.AddGestureRecognizer(_longPressGestureRecognizer);
166176
}
167177
}

src/Controls/src/Core/Handlers/Items2/iOS/ReorderableItemsViewController2.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ public class ReorderableItemsViewController2<TItemsView> : GroupableItemsViewCon
1414
bool _disposed;
1515
UILongPressGestureRecognizer _longPressGestureRecognizer;
1616

17+
#if MACCATALYST
18+
const double defaultMacCatalystPressDuration = 0.1;
19+
#endif
20+
1721
public ReorderableItemsViewController2(TItemsView reorderableItemsView, UICollectionViewLayout layout)
1822
: base(reorderableItemsView, layout)
1923
{
@@ -162,6 +166,12 @@ public void UpdateCanReorderItems()
162166
if (_longPressGestureRecognizer == null)
163167
{
164168
_longPressGestureRecognizer = new UILongPressGestureRecognizer(HandleLongPress);
169+
#if MACCATALYST
170+
// On Mac Catalyst, we disable the default drag interaction and instead handle dragging using a long press gesture recognizer.
171+
// Since a long press typically takes more time to trigger than the system's default drag interaction,
172+
// we reduce the minimum press duration to 0.1 seconds to better match the previous behavior.
173+
_longPressGestureRecognizer.MinimumPressDuration = defaultMacCatalystPressDuration;
174+
#endif
165175
CollectionView.AddGestureRecognizer(_longPressGestureRecognizer);
166176
}
167177
}

src/Controls/src/Core/Handlers/Shell/ShellHandler.Windows.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ private void OnLoaded(object sender, UI.Xaml.RoutedEventArgs e)
4242
{
4343
UpdateValue(nameof(Shell.FlyoutIcon));
4444
UpdateValue(nameof(Shell.FlyoutBackground));
45+
UpdateValue(nameof(Shell.FlyoutBackgroundImage));
4546
}
4647

4748
protected override void DisconnectHandler(ShellView platformView)
@@ -93,6 +94,7 @@ void OnPaneOpening(UI.Xaml.Controls.NavigationView sender, object args)
9394
{
9495
UpdateValue(nameof(Shell.FlyoutBackground));
9596
UpdateValue(nameof(Shell.FlyoutVerticalScrollMode));
97+
UpdateValue(nameof(Shell.FlyoutBackgroundImage));
9698
PlatformView.UpdateFlyoutBackdrop();
9799
PlatformView.UpdateFlyoutPosition();
98100
VirtualView.FlyoutIsPresented = true;
@@ -127,6 +129,16 @@ public static void MapFlyoutBackground(ShellHandler handler, Shell view)
127129
view.FlyoutBackgroundColor?.AsPaint());
128130
}
129131

132+
//TODO: Make it public in .NET 10.
133+
internal static void MapFlyoutBackgroundImage(ShellHandler handler, Shell view)
134+
{
135+
var provider = handler.GetRequiredService<IImageSourceServiceProvider>();
136+
if (handler?.PlatformView is not null && provider is not null)
137+
{
138+
handler.PlatformView.UpdateBackgroundImageSourceAsync(view.FlyoutBackgroundImage, provider, view.FlyoutBackgroundImageAspect).FireAndForget();
139+
}
140+
}
141+
130142
public static void MapFlyoutIcon(ShellHandler handler, Shell view)
131143
{
132144
var flyoutIcon = view.FlyoutIcon;

src/Controls/src/Core/Handlers/Shell/ShellHandler.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public partial class ShellHandler
3535
[nameof(Shell.FlyoutIcon)] = MapFlyoutIcon,
3636
[nameof(Shell.FlyoutContentTemplate)] = MapFlyout,
3737
[nameof(Shell.FlowDirection)] = MapFlowDirection,
38+
[nameof(Shell.FlyoutBackgroundImage)] = MapFlyoutBackgroundImage,
39+
[nameof(Shell.FlyoutBackgroundImageAspect)] = MapFlyoutBackgroundImage,
3840
#endif
3941
};
4042

src/Controls/src/Core/ImageElement.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ static void OnImageSourceChanged(BindableObject bindable, object oldValue, objec
2727
{
2828
var newSource = (ImageSource)newValue;
2929
var image = (IImageElement)bindable;
30-
if (newSource != null && image != null)
30+
31+
if (newSource is not null && image is not null)
32+
{
3133
newSource.SourceChanged += image.OnImageSourceSourceChanged;
34+
}
35+
3236
ImageSourceChanged(bindable, newSource);
3337
}
3438

@@ -37,8 +41,16 @@ static void OnImageSourceChanging(BindableObject bindable, object oldValue, obje
3741
var oldSource = (ImageSource)oldValue;
3842
var image = (IImageElement)bindable;
3943

40-
if (oldSource != null && image != null)
41-
oldSource.SourceChanged -= image.OnImageSourceSourceChanged;
44+
if (oldSource is not null)
45+
{
46+
if (image is not null)
47+
{
48+
oldSource.SourceChanged -= image.OnImageSourceSourceChanged;
49+
}
50+
51+
oldSource.Parent = null;
52+
}
53+
4254
ImageSourceChanging(oldSource);
4355
}
4456

src/Controls/src/Core/Layout/Grid.cs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ namespace Microsoft.Maui.Controls
99
[ContentProperty(nameof(Children))]
1010
public class Grid : Layout, IGridLayout
1111
{
12+
static readonly ColumnDefinitionCollection DefaultColumnDefinitions = new(new ColumnDefinition { Width = GridLength.Star });
13+
static readonly RowDefinitionCollection DefaultRowDefinitions = new(new RowDefinition { Height = GridLength.Star });
14+
1215
readonly Dictionary<IView, GridInfo> _viewInfo = new();
1316

1417
/// <summary>Bindable property for <see cref="ColumnDefinitions"/>.</summary>
@@ -354,6 +357,83 @@ protected override void OnBindingContextChanged()
354357
UpdateRowColumnBindingContexts();
355358
}
356359

360+
internal override void ComputeConstraintForView(View view)
361+
{
362+
var result = LayoutConstraint.None;
363+
364+
if (view.VerticalOptions.Alignment == LayoutAlignment.Fill && ViewHasFixedHeightDefinition(view))
365+
{
366+
result |= LayoutConstraint.VerticallyFixed;
367+
}
368+
369+
if (view.HorizontalOptions.Alignment == LayoutAlignment.Fill && ViewHasFixedWidthDefinition(view))
370+
{
371+
result |= LayoutConstraint.HorizontallyFixed;
372+
}
373+
374+
view.ComputedConstraint = result;
375+
}
376+
377+
bool ViewHasFixedHeightDefinition(BindableObject view)
378+
{
379+
var gridHasFixedHeight = (Constraint & LayoutConstraint.VerticallyFixed) != 0;
380+
381+
var row = GetRow(view);
382+
var rowSpan = GetRowSpan(view);
383+
var rowDefinitions = RowDefinitions;
384+
if (rowDefinitions?.Count is not > 0)
385+
{
386+
rowDefinitions = DefaultRowDefinitions;
387+
}
388+
389+
for (int i = row; i < row + rowSpan && i < rowDefinitions.Count; i++)
390+
{
391+
GridLength height = rowDefinitions[i].Height;
392+
393+
if (height.IsAuto)
394+
{
395+
return false;
396+
}
397+
398+
if (!gridHasFixedHeight && height.IsStar)
399+
{
400+
return false;
401+
}
402+
}
403+
404+
return true;
405+
}
406+
407+
bool ViewHasFixedWidthDefinition(BindableObject view)
408+
{
409+
var gridHasFixedWidth = (Constraint & LayoutConstraint.HorizontallyFixed) != 0;
410+
411+
var col = GetColumn(view);
412+
var colSpan = GetColumnSpan(view);
413+
var columnDefinitions = ColumnDefinitions;
414+
if (columnDefinitions?.Count is not > 0)
415+
{
416+
columnDefinitions = DefaultColumnDefinitions;
417+
}
418+
419+
for (int i = col; i < col + colSpan && i < columnDefinitions.Count; i++)
420+
{
421+
GridLength width = columnDefinitions[i].Width;
422+
423+
if (width.IsAuto)
424+
{
425+
return false;
426+
}
427+
428+
if (!gridHasFixedWidth && width.IsStar)
429+
{
430+
return false;
431+
}
432+
}
433+
434+
return true;
435+
}
436+
357437
void UpdateRowColumnBindingContexts()
358438
{
359439
var bindingContext = BindingContext;

src/Controls/src/Core/Layout/HorizontalStackLayout.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,17 @@ namespace Microsoft.Maui.Controls
77
public class HorizontalStackLayout : StackBase
88
{
99
protected override ILayoutManager CreateLayoutManager() => new HorizontalStackLayoutManager(this);
10+
11+
internal override void ComputeConstraintForView(View view)
12+
{
13+
if ((Constraint & LayoutConstraint.VerticallyFixed) != 0 && view.VerticalOptions.Alignment == LayoutAlignment.Fill)
14+
{
15+
view.ComputedConstraint = LayoutConstraint.VerticallyFixed;
16+
}
17+
else
18+
{
19+
view.ComputedConstraint = LayoutConstraint.None;
20+
}
21+
}
1022
}
1123
}

src/Controls/src/Core/Layout/StackLayout.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,31 @@ protected override ILayoutManager CreateLayoutManager()
3636
{
3737
return new StackLayoutManager(this);
3838
}
39+
40+
internal override void ComputeConstraintForView(View view)
41+
{
42+
if (Orientation == StackOrientation.Horizontal)
43+
{
44+
if ((Constraint & LayoutConstraint.VerticallyFixed) != 0 && view.VerticalOptions.Alignment == LayoutAlignment.Fill)
45+
{
46+
view.ComputedConstraint = LayoutConstraint.VerticallyFixed;
47+
}
48+
else
49+
{
50+
view.ComputedConstraint = LayoutConstraint.None;
51+
}
52+
}
53+
else
54+
{
55+
if ((Constraint & LayoutConstraint.HorizontallyFixed) != 0 && view.HorizontalOptions.Alignment == LayoutAlignment.Fill)
56+
{
57+
view.ComputedConstraint = LayoutConstraint.HorizontallyFixed;
58+
}
59+
else
60+
{
61+
view.ComputedConstraint = LayoutConstraint.None;
62+
}
63+
}
64+
}
3965
}
4066
}

src/Controls/src/Core/Layout/VerticalStackLayout.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,17 @@ namespace Microsoft.Maui.Controls
77
public class VerticalStackLayout : StackBase
88
{
99
protected override ILayoutManager CreateLayoutManager() => new VerticalStackLayoutManager(this);
10+
11+
internal override void ComputeConstraintForView(View view)
12+
{
13+
if ((Constraint & LayoutConstraint.HorizontallyFixed) != 0 && view.HorizontalOptions.Alignment == LayoutAlignment.Fill)
14+
{
15+
view.ComputedConstraint = LayoutConstraint.HorizontallyFixed;
16+
}
17+
else
18+
{
19+
view.ComputedConstraint = LayoutConstraint.None;
20+
}
21+
}
1022
}
1123
}

src/Controls/src/Core/Platform/Android/Extensions/FormattedStringExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ internal static SpannableString ToSpannableStringNewWay(
116116
if (font.IsDefault && defaultFont.HasValue)
117117
font = defaultFont.Value;
118118
if (!font.IsDefault)
119-
spannable.SetSpan(new PlatformFontSpan(context ?? AAplication.Context, font.ToTypeface(fontManager), font.AutoScalingEnabled, (float)font.Size), start, end, SpanTypes.InclusiveInclusive);
119+
spannable.SetSpan(new PlatformFontSpan(context ?? AAplication.Context, font.ToTypeface(fontManager), font.AutoScalingEnabled, (float)fontManager.GetFontSize(font).Value), start, end, SpanTypes.InclusiveInclusive);
120120

121121
// TextDecorations
122122
var textDecorations = span.IsSet(Span.TextDecorationsProperty)

0 commit comments

Comments
 (0)