Поиск по оболочке Xamarin.Forms

Download Sample Скачайте пример

Оболочка Xamarin.Forms включает встроенные функции поиска, предоставляемые классом SearchHandler. Возможность поиска можно добавить на страницу, указав для присоединенного свойства Shell.SearchHandler в качестве значения объект подкласса SearchHandler. После этого в верхней части страницы появится поле поиска:

Screenshot of a Shell SearchHandler, on iOS and Android

При вводе запроса в поле поиска обновляется свойство Query, а при каждом обновлении выполняется метод OnQueryChanged. Этот метод может быть переопределен для заполнения данными области поисковых подсказок:

Screenshot of a search results in a Shell SearchHandler, on iOS and Android

При выборе результата из области поисковых подсказок выполняется метод 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, чтобы поисковые подсказки отображались по мере ввода поискового запроса пользователем:

Screenshot of search results in a Shell SearchHandler, on iOS and Android, with results for the partial string M.

По мере изменения поискового запроса данные в области поисковых подсказок обновляются:

Screenshot of search results in a Shell SearchHandler, on iOS and Android, with results for the partial string M o n.

При выборе результата поиска происходит переход к MonkeyDetailPage и отображается страница сведений о выбранной обезьяне:

Screenshot of monkey details, on iOS and Android

Определения внешнего вида элементов в результатах поиска

Помимо отображения данных 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.

На следующих снимках экрана представлены результаты применения шаблона для всех элементов в области поисковых подсказок:

Screenshot of templated search results in a Shell SearchHandler, on iOS and Android

Дополнительные сведения о шаблонах данных см. в разделе Общие сведения о шаблонах данных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);