Skip to content

Commit e28d3d0

Browse files
CopilotVetle444Copilot
authored
SearchPage: Add ScrollableHeader, OnBackButtonPressed, use OnHandlerChanged, remove legacy safe area handling (#819)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Vetle444 <35739538+Vetle444@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Vetle444 <vetle_96@live.no>
1 parent 670cb7c commit e28d3d0

File tree

4 files changed

+71
-41
lines changed

4 files changed

+71
-41
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## [55.3.0]
2+
- [SearchPage] Added `ScrollableHeader` property to allow consumers to provide a header that scrolls with search results.
3+
- [SearchPage] Replaced `OnLoaded`/`OnUnloaded` event subscriptions with `OnHandlerChanged` override.
4+
- [SearchPage] Removed old iOS safe area handling in favor of .NET 10 `SafeAreaEdges` (consumers should set safe area themselves).
5+
- [SearchPage] Android back button now executes `CancelCommand`, allowing consumers to override close behavior with their own navigation service.
6+
17
## [55.2.7]
28
- [Android][Modal] Fixed memory leak when popping modal pages wrapped in NavigationPage, caused by StackNavigationManager not clearing references on disconnect (dotnet/maui#34456)
39
- [Android][Button] Fixed memory leak caused by strong reference from platform MaterialButton to virtual Button

src/app/Components/ComponentsSamples/Searching/SearchPageSamples.xaml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,22 @@
1919
<dui:SearchPage.BindingContext>
2020
<searching:SearchPageSamplesPageViewModel />
2121
</dui:SearchPage.BindingContext>
22+
<dui:SearchPage.ScrollableHeader>
23+
<dui:Label Text="{x:Static localizedStrings:LocalizedStrings.SearchPage_PlaceholderText}"
24+
Style="{dui:Styles Label=SectionHeader}"
25+
Margin="{dui:Thickness Left=content_margin_medium, Top=content_margin_medium}" />
26+
</dui:SearchPage.ScrollableHeader>
2227
<dui:SearchPage.HintView>
23-
<dui:Label Text="{x:Static localizedStrings:LocalizedStrings.SearchPage_HintText}"
24-
VerticalOptions="CenterAndExpand"
25-
HorizontalOptions="CenterAndExpand" />
28+
<Grid RowDefinitions="Auto, *">
29+
<dui:Label Text="{x:Static localizedStrings:LocalizedStrings.SearchPage_PlaceholderText}"
30+
Style="{dui:Styles Label=SectionHeader}"
31+
Margin="{dui:Thickness Left=content_margin_medium, Top=content_margin_medium}" />
32+
33+
<dui:Label Text="{x:Static localizedStrings:LocalizedStrings.SearchPage_HintText}"
34+
VerticalOptions="CenterAndExpand"
35+
HorizontalOptions="CenterAndExpand"
36+
Grid.Row="1" />
37+
</Grid>
2638
</dui:SearchPage.HintView>
2739
<dui:SearchPage.NoResultView>
2840
<dui:Label Text="{x:Static localizedStrings:LocalizedStrings.SearchPage_NoResultText}"

src/library/DIPS.Mobile.UI/Components/Searching/SearchPage.Properties.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ public View FooterView
3131
set => SetValue(FooterViewProperty, value);
3232
}
3333

34+
/// <summary>
35+
/// A view displayed at the top of the result list that scrolls with the content.
36+
/// </summary>
37+
public View? ScrollableHeader
38+
{
39+
get => (View?)GetValue(ScrollableHeaderProperty);
40+
set => SetValue(ScrollableHeaderProperty, value);
41+
}
42+
3443
[Obsolete("Setting Content property is the same as setting EmptyResultView")]
3544
public new View? Content { get; set; }
3645

@@ -222,6 +231,12 @@ public bool AutoHideLastDivider
222231
typeof(SearchPage),
223232
propertyChanged: (bindable, _, _) => ((SearchPage)bindable).OnFooterViewChanged());
224233

234+
public static readonly BindableProperty ScrollableHeaderProperty = BindableProperty.Create(
235+
nameof(ScrollableHeader),
236+
typeof(View),
237+
typeof(SearchPage),
238+
propertyChanged: (bindable, _, _) => ((SearchPage)bindable).OnScrollableHeaderChanged());
239+
225240
public static readonly BindableProperty IsAutocorrectEnabledProperty = BindableProperty.Create(
226241
nameof(IsAutocorrectEnabled),
227242
typeof(bool),

src/library/DIPS.Mobile.UI/Components/Searching/SearchPage.cs

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
#if __IOS__
2-
using DIPS.Mobile.UI.Components.Searching.iOS;
3-
using UIKit;
4-
#endif
5-
1+
using DIPS.Mobile.UI.Components.Dividers;
62
using DIPS.Mobile.UI.Components.Lists;
73
using DIPS.Mobile.UI.Extensions;
84
using DIPS.Mobile.UI.Internal;
@@ -24,12 +20,10 @@ public abstract partial class SearchPage : ContentPage
2420

2521
public SearchPage()
2622
{
27-
Loaded += OnLoaded;
28-
Unloaded += OnUnLoaded;
2923

3024
//Searchbar
3125
SearchBar = new SearchBar { AutomationId = "SearchBar".ToDUIAutomationId<SearchPage>(), HasCancelButton = true, HasBusyIndication = true, ShouldCloseKeyboardOnReturnKeyTapped = true };
32-
SearchBar.SetAppThemeColor(SearchBar.BarColorProperty, ColorName.color_surface_default);
26+
SearchBar.SetAppThemeColor(SearchBar.BarColorProperty, Shell.Shell.BackgroundColorName);
3327

3428
#if __ANDROID__ //Colors are different on Android due to no inner white frame
3529
SearchBar.SetAppThemeColor(SearchBar.TextColorProperty,
@@ -38,6 +32,8 @@ public SearchPage()
3832
ColorName.color_icon_default);
3933
SearchBar.SetAppThemeColor(SearchBar.PlaceholderColorProperty,
4034
ColorName.color_text_subtle);
35+
SearchBar.SetAppThemeColor(SearchBar.CancelButtonTextColorProperty,
36+
ColorName.color_text_action);
4137
#else
4238
SearchBar.SetAppThemeColor(SearchBar.SearchFieldBackgroundColorProperty,
4339
BackgroundColorName);
@@ -75,11 +71,11 @@ public SearchPage()
7571
{
7672
new()
7773
{
78-
Height = GridLength.Auto // Space for safe area ios
79-
},
74+
Height = GridLength.Auto // Space for the search bar
75+
},
8076
new()
8177
{
82-
Height = GridLength.Auto // Space for the search bar
78+
Height = GridLength.Auto // Divider
8379
},
8480
new()
8581
{
@@ -93,7 +89,12 @@ public SearchPage()
9389
RowSpacing = 0
9490
};
9591

96-
m_grid.Add(SearchBar, 0, 1);
92+
m_grid.Add(SearchBar, 0, 0);
93+
94+
m_grid.Add(new Divider
95+
{
96+
Margin = new Thickness(0, Sizes.GetSize(SizeName.size_1), 0, 0)
97+
}, 0, 1);
9798

9899
OnSearchModeChanged();
99100

@@ -109,41 +110,20 @@ private void OnCollectionViewScrolled(object? sender, ItemsViewScrolledEventArgs
109110
SearchBar.Unfocus();
110111
}
111112

112-
private void OnUnLoaded(object? sender, EventArgs e)
113+
protected override void OnHandlerChanged()
113114
{
114-
Loaded -= OnLoaded;
115-
Unloaded -= OnUnLoaded;
116-
m_resultCollectionView.Scrolled -= OnCollectionViewScrolled;
115+
base.OnHandlerChanged();
117116

118-
SearchBar.Focused -= OnSearchBarFocused;
117+
if (Handler is null)
118+
return;
119119

120-
}
121-
122-
private void OnLoaded(object? sender, EventArgs e)
123-
{
124120
SetSearchState(SearchStates.NeedsSearchHint);
125121
if (ShouldAutoFocus)
126122
{
127123
SearchBar.Focus();
128124
}
129125

130126
SearchBar.Focused += OnSearchBarFocused;
131-
132-
#if __IOS__
133-
if (OperatingSystem.IsIOSVersionAtLeast(14, 1))
134-
{
135-
var safeAreaInsetsTop = UIApplication.SharedApplication.KeyWindow.SafeAreaInsets.Top;
136-
137-
var topBoxView = new BoxView
138-
{
139-
BackgroundColor = SearchBar.BarColor, HeightRequest = safeAreaInsetsTop
140-
};
141-
142-
m_grid.Children.Insert(0, topBoxView);
143-
144-
topBoxView.Margin = new Thickness(0, -safeAreaInsetsTop, 0, 0);
145-
}
146-
#endif
147127
}
148128

149129
private void OnSearchBarFocused(object? sender, EventArgs eventArgs)
@@ -162,7 +142,19 @@ private void TextWasClearedFromClick()
162142

163143
private static void OnCancel()
164144
{
165-
Application.Current!.MainPage!.Navigation.PopAsync();
145+
Application.Current?.Windows[0].Navigation.PopModalAsync();
146+
}
147+
148+
/// <inheritdoc />
149+
protected override bool OnBackButtonPressed()
150+
{
151+
if (CancelCommand.CanExecute(null))
152+
{
153+
CancelCommand.Execute(null);
154+
return true;
155+
}
156+
157+
return base.OnBackButtonPressed();
166158
}
167159

168160
private void SearchBarOnTextChanged(object? sender, TextChangedEventArgs e)
@@ -264,6 +256,11 @@ private void OnSearchModeChanged()
264256
ReturnType.Search;
265257
}
266258

259+
private void OnScrollableHeaderChanged()
260+
{
261+
m_resultCollectionView.Header = ScrollableHeader;
262+
}
263+
267264
private void OnFooterViewChanged()
268265
{
269266
if (m_footerView is not null)

0 commit comments

Comments
 (0)