Поиск по оболочке Xamarin.Forms
Оболочка Xamarin.Forms включает встроенные функции поиска, предоставляемые классом SearchHandler
. Возможность поиска можно добавить на страницу, указав для присоединенного свойства Shell.SearchHandler
в качестве значения объект подкласса SearchHandler
. После этого в верхней части страницы появится поле поиска:
При вводе запроса в поле поиска обновляется свойство Query
, а при каждом обновлении выполняется метод OnQueryChanged
. Этот метод может быть переопределен для заполнения данными области поисковых подсказок:
При выборе результата из области поисковых подсказок выполняется метод OnItemSelected
. Этот метод может быть переопределен, чтобы вызвать соответствующую реакцию, например переход на страницу подробных сведений.
Создание SearchHandler
Чтобы добавить функцию поиска в приложение оболочки, создайте класс, производный от класса SearchHandler
, и переопределите методы OnQueryChanged
и OnItemSelected
:
public class AnimalSearchHandler : SearchHandler
{
public IList<Animal> Animals { get; set; }
public Type SelectedItemNavigationTarget { get; set; }
protected override void OnQueryChanged(string oldValue, string newValue)
{
base.OnQueryChanged(oldValue, newValue);
if (string.IsNullOrWhiteSpace(newValue))
{
ItemsSource = null;
}
else
{
ItemsSource = Animals
.Where(animal => animal.Name.ToLower().Contains(newValue.ToLower()))
.ToList<Animal>();
}
}
protected override async void OnItemSelected(object item)
{
base.OnItemSelected(item);
// Let the animation complete
await Task.Delay(1000);
ShellNavigationState state = (App.Current.MainPage as Shell).CurrentState;
// The following route works because route names are unique in this application.
await Shell.Current.GoToAsync($"{GetNavigationTarget()}?name={((Animal)item).Name}");
}
string GetNavigationTarget()
{
return (Shell.Current as AppShell).Routes.FirstOrDefault(route => route.Value.Equals(SelectedItemNavigationTarget)).Key;
}
}
Переопределение OnQueryChanged
имеет два аргумента: oldValue
содержит предыдущий поисковый запрос, а newValue
— текущий поисковый запрос. Область поисковых подсказок можно обновлять, задавая свойству SearchHandler.ItemsSource
значение коллекции IEnumerable
с элементами, которые соответствуют текущему поисковому запросу.
Когда пользователь выбирает результат поиска, выполняется переопределение метода OnItemSelected
и присваивается значение свойству SelectedItem
. В нашем примере этот метод переходит на другую страницу, которая отображает данные о выбранных Animal
. Дополнительные сведения о навигации см. в разделе Навигация по оболочке Xamarin.Forms.
Примечание.
Дополнительные свойства SearchHandler
позволяют управлять внешним видом поля поиска.
Использование SearchHandler
Подкласс SearchHandler
можно использовать, присваивая присоединенному свойству Shell.SearchHandler
значение объекта соответствующего типа на странице использования:
<ContentPage ...
xmlns:controls="clr-namespace:Xaminals.Controls">
<Shell.SearchHandler>
<controls:AnimalSearchHandler Placeholder="Enter search term"
ShowsResults="true"
DisplayMemberName="Name" />
</Shell.SearchHandler>
...
</ContentPage>
Эквивалентный код на C# выглядит так:
Shell.SetSearchHandler(this, new AnimalSearchHandler
{
Placeholder = "Enter search term",
ShowsResults = true,
DisplayMemberName = "Name"
});
Метод AnimalSearchHandler.OnQueryChanged
возвращает List
объектов Animal
. Свойству DisplayMemberName
присваивается свойство Name
каждого объекта Animal
, а значит, отображаемые в области поисковых подсказок данные будут содержать названия каждого животного.
Свойству ShowsResults
присваивается значение true
, чтобы поисковые подсказки отображались по мере ввода поискового запроса пользователем:
По мере изменения поискового запроса данные в области поисковых подсказок обновляются:
При выборе результата поиска происходит переход к MonkeyDetailPage
и отображается страница сведений о выбранной обезьяне:
Определения внешнего вида элементов в результатах поиска
Помимо отображения данных string
в результатах поиска, вы можете изменить внешний вид каждого элемента результатов поиска, присвоив свойству SearchHandler.ItemTemplate
значение DataTemplate
:
<ContentPage ...
xmlns:controls="clr-namespace:Xaminals.Controls">
<Shell.SearchHandler>
<controls:AnimalSearchHandler Placeholder="Enter search term"
ShowsResults="true">
<controls:AnimalSearchHandler.ItemTemplate>
<DataTemplate>
<Grid Padding="10"
ColumnDefinitions="0.15*,0.85*">
<Image Source="{Binding ImageUrl}"
HeightRequest="40"
WidthRequest="40" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold"
VerticalOptions="Center" />
</Grid>
</DataTemplate>
</controls:AnimalSearchHandler.ItemTemplate>
</controls:AnimalSearchHandler>
</Shell.SearchHandler>
...
</ContentPage>
Эквивалентный код на C# выглядит так:
Shell.SetSearchHandler(this, new AnimalSearchHandler
{
Placeholder = "Enter search term",
ShowsResults = true,
ItemTemplate = new DataTemplate(() =>
{
Grid grid = new Grid { Padding = 10 };
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.15, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.85, GridUnitType.Star) });
Image image = new Image { HeightRequest = 40, WidthRequest = 40 };
image.SetBinding(Image.SourceProperty, "ImageUrl");
Label nameLabel = new Label { FontAttributes = FontAttributes.Bold, VerticalOptions = LayoutOptions.Center };
nameLabel.SetBinding(Label.TextProperty, "Name");
grid.Children.Add(image);
grid.Children.Add(nameLabel, 1, 0);
return grid;
})
});
Указанные в DataTemplate
элементы определяют внешний вид каждого элемента в области поисковых подсказок. В нашем примере компоновка внутри DataTemplate
определяется значением Grid
. Grid
содержит объект Image
и объект Label
, оба из которых содержат привязки к свойствам каждого объекта Monkey
.
На следующих снимках экрана представлены результаты применения шаблона для всех элементов в области поисковых подсказок:
Дополнительные сведения о шаблонах данных см. в разделе Общие сведения о шаблонах данныхXamarin.Forms.
Видимость поля поиска
Когда в верхней части страницы добавляется SearchHandler
, поле поиска по умолчанию является видимым и полностью развернутым. Тем не менее это поведение можно изменить, задав в свойстве SearchHandler.SearchBoxVisibility
один из членов перечисления SearchBoxVisibility
:
Hidden
— поле поиска не отображается и недоступно;Collapsible
— поле поиска является скрытым, пока пользователь не выполнит действие, открывающее его; Для отображения поля поиска в iOS нужно инициировать "подпрыгивание" содержимого страницы в вертикальном направлении, а в Android — коснуться значка вопросительного знака.Expanded
— поле поиска является видимым и полностью развернутым. Это значение по умолчанию для свойстваSearchBoxVisibility
.
Внимание
В iOS для свертываемого поля поиска требуется iOS 11 или более поздней версии.
В следующем примере показано, как скрыть поле поиска:
<ContentPage ...
xmlns:controls="clr-namespace:Xaminals.Controls">
<Shell.SearchHandler>
<controls:AnimalSearchHandler SearchBoxVisibility="Hidden"
... />
</Shell.SearchHandler>
...
</ContentPage>
Фокус поля поиска
При касании поля поиска отображается экранная клавиатура, а в поле поиска появляется фокус ввода. Это можно также реализовать программным образом, вызвав метод Focus
, который пытается задать фокус ввода в поле поиска и возвращает true
при успешном выполнении. Когда поле поиска получает фокус, активируется событие Focused
и вызывается переопределяемый метод OnFocused
.
Когда в поле поиска есть фокус ввода, касание экрана в любом другом месте скрывает экранную клавиатуру и поле теряет фокус ввода. Это можно также реализовать программным образом, вызвав метод Unfocus
. Когда поле поиска теряет фокус, активируется событие Unfocused
и вызывается переопределяемый метод OnUnfocus
.
Состояние фокуса в поле поиска можно получить с помощью свойства IsFocused
, которое возвращает true
, если SearchHandler
в этот момент имеет фокус ввода.
Клавиатура SearchHandler
Клавиатуру, отображаемую при взаимодействии пользователя с SearchHandler
, можно задать программно с помощью свойства Keyboard
, используя следующие свойства класса Keyboard
:
Chat
— это текстовая клавиатура с эмодзи.Default
— это клавиатура по умолчанию.Email
используется для ввода адресов электронной почты.Numeric
— цифровая клавиатура.Plain
предназначена для ввода текста, если нет заданныхKeyboardFlags
.Telephone
— клавиатура для ввода телефонных номеров.Text
— текстовая клавиатура.Url
— клавиатура для ввода путей к файлам и веб-адресов.
Это можно сделать в XAML следующим образом:
<SearchHandler Keyboard="Email" />
Эквивалентный код на C# выглядит так:
SearchHandler searchHandler = new SearchHandler { Keyboard = Keyboard.Email };
Класс Keyboard
также имеет фабричный метод Create
, который может использоваться для настройки клавиатуры, задавая регистр букв, проверку орфографии и режим подсказок. Значения перечисления KeyboardFlags
задаются как аргументы метода, при этом возвращается настроенное свойство Keyboard
. Перечисление KeyboardFlags
имеет такие значения:
None
указывает, что клавиатура не имеет никаких дополнительных функций.CapitalizeSentence
указывает, что первые слова во всех вводимых предложениях автоматически начинаются с прописных букв.Spellcheck
указывает, что для вводимого текста выполняется проверка орфографии.Suggestions
указывает, что для вводимых слов предлагается завершение.CapitalizeWord
указывает, что все слова автоматически начинаются с прописных букв.CapitalizeCharacter
указывает, что все символы автоматически пишутся прописными буквами.CapitalizeNone
указывает, что автоматическая подстановка прописных букв не выполняется.All
указывает, что для вводимого текста выполняется проверка орфографии, завершение слов и автоматическое написание предложений с прописной буквы.
В следующем примере кода XAML показано, как настроить значение по умолчанию Keyboard
, чтобы включить предложение завершения слов и написание всех символов прописными буквами:
<SearchHandler Placeholder="Enter search terms">
<SearchHandler.Keyboard>
<Keyboard x:FactoryMethod="Create">
<x:Arguments>
<KeyboardFlags>Suggestions,CapitalizeCharacter</KeyboardFlags>
</x:Arguments>
</Keyboard>
</SearchHandler.Keyboard>
</SearchHandler>
Эквивалентный код на C# выглядит так:
SearchHandler searchHandler = new SearchHandler { Placeholder = "Enter search terms" };
searchHandler.Keyboard = Keyboard.Create(KeyboardFlags.Suggestions | KeyboardFlags.CapitalizeCharacter);