Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## [55.5.0]
- [iOS][BottomSheet] Replaced MAUI SearchBar with native UISearchController for bottom sheet search, integrating the search bar into the navigation bar
- [Android][BottomSheet] Replaced MAUI SearchBar with Material 3 SearchBar and SearchView components for bottom sheet search
- [ContentPage] Added `SearchBehavior` property for native platform search on regular pages (iOS: UISearchController, Android: Material 3 SearchBar + SearchView)

## [55.4.0]
- [iOS][BottomSheet] Use native UINavigationBar for bottom sheet header with centered title, system close/back buttons, and proper blur behavior
- [Android][BottomSheet] Fixed edge-to-edge constraints not applying until scroll when start Positioning is Large
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
<dui:NavigationListItem Title="{x:Static localizedStrings:LocalizedStrings.BottomSheet}"
Subtitle="{x:Static localizedStrings:LocalizedStrings.BottomSheet_OpenNotClosableInteracting}"
Command="{dui:OpenBottomSheetCommand {x:Type sheets:BottomSheetNotClosableByInteracting}}"
VerticalOptions="Start"
HasBottomDivider="True" />

<dui:NavigationListItem Title="Open with search"
Subtitle="BottomSheet with native search field"
Command="{dui:OpenBottomSheetCommand {x:Type sheets:BottomSheetWithSearch}}"
VerticalOptions="Start" />
</dui:VerticalStackLayout>
</dui:ContentPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>

<dui:BottomSheet xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:dui="http://dips.com/mobile.ui"
xmlns:sheets="clr-namespace:Components.ComponentsSamples.BottomSheets.Sheets"
xmlns:sampleData="clr-namespace:Components.SampleData"
x:Class="Components.ComponentsSamples.BottomSheets.Sheets.BottomSheetWithSearch"
x:DataType="sheets:BottomSheetWithSearchViewModel"
Title="Search"
HasSearchBar="True"
SearchCommand="{Binding SearchCommand}"
Positioning="Large">

<dui:BottomSheet.BindingContext>
<sheets:BottomSheetWithSearchViewModel />
</dui:BottomSheet.BindingContext>

<CollectionView ItemsSource="{Binding People}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="{x:Type sampleData:Person}">
<dui:ListItem Title="{Binding DisplayName}"
HasBottomDivider="True" />
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.EmptyView>
<dui:Label Text="No results found"
HorizontalOptions="Center"
Margin="{dui:Thickness Top=content_margin_large}"
Style="{dui:Styles Label=UI200}" />
</CollectionView.EmptyView>
</CollectionView>

</dui:BottomSheet>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Components.ComponentsSamples.BottomSheets.Sheets;

public partial class BottomSheetWithSearch
{
public BottomSheetWithSearch()
{
InitializeComponent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Windows.Input;
using Components.SampleData;
using DIPS.Mobile.UI.MVVM;

namespace Components.ComponentsSamples.BottomSheets.Sheets;

public class BottomSheetWithSearchViewModel : ViewModel
{
private List<Person> m_people;
private readonly List<Person> m_originalPeople;

public BottomSheetWithSearchViewModel()
{
People = SampleDataStorage.People.ToList();
m_originalPeople = People.ToList();
SearchCommand = new Command<string>(FilterItems);
}

private void FilterItems(string filterText)
{
if (string.IsNullOrEmpty(filterText))
{
People = m_originalPeople.ToList();
}
else
{
People = m_originalPeople
.Where(p => p.DisplayName.ToLower().Contains(filterText.ToLower()))
.ToList();
}
}

public List<Person> People
{
get => m_people;
set => RaiseWhenSet(ref m_people, value);
}

public ICommand SearchCommand { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>

<dui:ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:dui="http://dips.com/mobile.ui"
xmlns:search="clr-namespace:DIPS.Mobile.UI.Components.Pages.Search;assembly=DIPS.Mobile.UI"
xmlns:searching="clr-namespace:Components.ComponentsSamples.Searching"
xmlns:sampleData="clr-namespace:Components.SampleData"
x:Class="Components.ComponentsSamples.Searching.NativeSearchPageSamples"
x:DataType="searching:NativeSearchPageSamplesViewModel"
Title="Native Search">

<dui:ContentPage.BindingContext>
<searching:NativeSearchPageSamplesViewModel />
</dui:ContentPage.BindingContext>

<dui:ContentPage.SearchBehavior>
<search:SearchBehavior SearchCommand="{Binding SearchCommand}" />
</dui:ContentPage.SearchBehavior>

<CollectionView ItemsSource="{Binding People}"
Margin="{dui:Thickness Left=content_margin_medium, Right=content_margin_medium}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="{x:Type sampleData:Person}">
<dui:ListItem Title="{Binding DisplayName}"
HasBottomDivider="True" />
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.EmptyView>
<dui:Label Text="No results found"
HorizontalOptions="Center"
Margin="{dui:Thickness Top=content_margin_large}"
Style="{dui:Styles Label=UI200}" />
</CollectionView.EmptyView>
</CollectionView>

</dui:ContentPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Components.ComponentsSamples.Searching;

public partial class NativeSearchPageSamples
{
public NativeSearchPageSamples()
{
InitializeComponent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Windows.Input;
using Components.SampleData;
using DIPS.Mobile.UI.MVVM;

namespace Components.ComponentsSamples.Searching;

public class NativeSearchPageSamplesViewModel : ViewModel
{
private List<Person> m_people;
private readonly List<Person> m_originalPeople;

public NativeSearchPageSamplesViewModel()
{
People = SampleDataStorage.People.ToList();
m_originalPeople = People.ToList();
SearchCommand = new Command<string>(FilterItems);
}

private void FilterItems(string filterText)
{
if (string.IsNullOrEmpty(filterText))
{
People = m_originalPeople.ToList();
}
else
{
People = m_originalPeople
.Where(p => p.DisplayName.ToLower().Contains(filterText.ToLower()))
.ToList();
}
}

public List<Person> People
{
get => m_people;
set => RaiseWhenSet(ref m_people, value);
}

public ICommand SearchCommand { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
HasBottomDivider="True"/>

<dui:NavigationListItem Title="Search page"
Command="{helpers:NavigationCommand {x:Type searching:SearchPageSamples}}" />
Command="{helpers:NavigationCommand {x:Type searching:SearchPageSamples}}"
HasBottomDivider="True" />

<dui:NavigationListItem Title="Native search (SearchBehavior)"
Command="{helpers:NavigationCommand {x:Type searching:NativeSearchPageSamples}}" />
</dui:VerticalStackLayout>
</dui:ContentPage>
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Paint = Android.Graphics.Paint;
using System.ComponentModel;
using DIPS.Mobile.UI.API.Library;
using DIPS.Mobile.UI.Components.BottomSheets.Android;
using DIPS.Mobile.UI.Components.BottomSheets.Header;
using SearchBar = DIPS.Mobile.UI.Components.Searching.SearchBar;
using View = Microsoft.Maui.Controls.View;
Expand All @@ -35,7 +36,7 @@ public partial class BottomSheetHandler : ContentViewHandler
internal AView? m_bottomBar;

private static AView? s_mEmptyNonFitToContentView;
private AView? m_searchBarView;
private BottomSheetSearchField? m_searchField;
private BottomSheetHeader m_bottomSheetHeader;
private List<WeakReference<SearchBar>> m_weakSearchBars = [];
private WeakReference<AView>? m_weakCurrentFocusedSearchBar;
Expand Down Expand Up @@ -88,9 +89,15 @@ public AView OnBeforeOpening(IMauiContext mauiContext, Context context, AView bo
m_bottomSheetHeader = new BottomSheetHeader(m_bottomSheet);
bottomSheetLayout.AddView(m_bottomSheetHeader.ToPlatform(mauiContext));

m_searchBarView = m_bottomSheet.SearchBar.ToPlatform(mauiContext);
bottomSheetLayout.AddView(m_searchBarView);
// Create native Material 3 search field
m_searchField = new BottomSheetSearchField(context, m_bottomSheet);
bottomSheetLayout.AddView(m_searchField.View);
ToggleSearchBar();

// Set focus/unfocus actions on the BottomSheet
m_bottomSheet.FocusSearchAction = () => m_searchField?.Focus();
m_bottomSheet.UnfocusSearchAction = () => m_searchField?.Unfocus();

FindAndSetupSearchBars();

bottomSheetLayout.AddView(bottomSheetAndroidView);
Expand Down Expand Up @@ -134,23 +141,15 @@ private void FindAndSetupSearchBars()
searchBar.Focused += SearchBarOnFocused;
searchBar.Unfocused += SearchBarOnUnfocused;
}

// Also, setup the internal search bar in BottomSheet
if (m_bottomSheet.SearchBar is { } searchBarInternal)
{
searchBarInternal.Focused += SearchBarOnFocused;
searchBarInternal.Unfocused += SearchBarOnUnfocused;
}

}


private void ToggleSearchBar()
{
if (m_searchBarView == null)
if (m_searchField?.View == null)
return;

m_searchBarView.Visibility = m_bottomSheet.HasSearchBar ? ViewStates.Visible : ViewStates.Gone;
m_searchField.View.Visibility = m_bottomSheet.HasSearchBar ? ViewStates.Visible : ViewStates.Gone;
}

private void SearchBarOnUnfocused(object? sender, EventArgs e)
Expand Down Expand Up @@ -246,12 +245,11 @@ protected override void DisconnectHandler(ContentViewGroup platformView)
searchBar.Unfocused -= SearchBarOnUnfocused;
}

// Also, dispose the internal search bar in BottomSheet
if (m_bottomSheet.SearchBar is { } searchBarInternal)
{
searchBarInternal.Focused -= SearchBarOnFocused;
searchBarInternal.Unfocused -= SearchBarOnUnfocused;
}
// Clean up native search field
m_searchField?.Cleanup();
m_searchField = null;
m_bottomSheet.FocusSearchAction = null;
m_bottomSheet.UnfocusSearchAction = null;
}

/// <summary>
Expand Down
Loading