Поделиться через


Потяните, чтобы обновить

Обновление путем оттягивания позволяет пользователю с помощью сенсорного ввода потянуть список данных вниз, чтобы получить дополнительные данные. Обновление путем оттягивания широко используется на устройствах с сенсорным экраном. Вы можете использовать указанные здесь API для реализации функции pull-to-refresh в вашем приложении.

GIF-файл

Это правильный элемент управления?

Используйте обновление путем оттягивания при работе со списком или сеткой с данными, которые пользователь может регулярно обновлять, и если ваше приложение предназначено для работы на устройствах, рассчитанных на сенсорное управление.

Вы также можете использовать RefreshVisualizer для создания согласованного интерфейса обновления, вызываемого другими способами, например кнопкой обновления.

Обновить элементы управления

Функция "pull-to-refresh" активируется двумя элементами управления.

  • RefreshContainer — ContentControl, который предоставляет оболочку для интерфейса обновления по запросу. Он обрабатывает сенсорные взаимодействия и управляет состоянием внутреннего визуализатора обновления.
  • RefreshVisualizer — инкапсулирует визуализацию обновления, описанную в следующем разделе.

Основной элемент управления — RefreshContainer, который размещается в виде оболочки вокруг содержимого, которое пользователь извлекает для активации обновления. RefreshContainer работает только с сенсорным экраном, поэтому мы также рекомендуем использовать кнопку "Обновить" для пользователей, у которых нет сенсорного интерфейса. Кнопку "Обновить" можно разместить в подходящем месте в приложении — на панели команд или в месте, находящемся рядом с обновляемой поверхностью.

Обновить визуализацию

Визуализация обновления по умолчанию — это циклический индикатор хода выполнения, который сообщает о том, когда произойдет обновление, и о ходе обновления после его запуска. Визуализатор обновления имеет 5 состояний.

Расстояние, которое пользователь должен вытащить из списка, чтобы инициировать обновление, называется пороговым значением. Состояние визуализатора определяется состоянием вытягивания, так как оно относится к этому порогу. Возможные значения содержатся в перечислении RefreshVisualizerState .

Бездействие

Состояние визуализатора по умолчанию — простой. Пользователь не взаимодействует с RefreshContainer посредством сенсорного ввода и обновление не выполняется.

Визуальные признаки работы визуализатора обновления отсутствуют.

Взаимодействие

Когда пользователь извлекает список в направлении, указанном свойством PullDirection, и до достижения порогового значения визуализатор находится в состоянии "Взаимодействие ".

  • Если пользователь освобождает элемент управления во время этого состояния, элемент управления возвращается в состояние простоя.

    Пороговое значение перед обновлением

    Визуально значок отображается как отключенный (непрозрачность 60 %). Кроме того, значок производит один полный оборот с помощью действия прокрутки.

  • Если пользователь извлекает список за пороговое значение, визуализатор переходит из взаимодействия в ожидание.

    Обновление при достижении порога методом потягивания

    Визуально значок переключается на 100% непрозрачности и увеличивается в размере до 150%, а затем уменьшается обратно до 100% во время перехода.

Не завершено

Когда пользователь вытащил список за пороговое значение, визуализатор находится в состоянии ожидания .

  • Если пользователь перемещает список обратно над пороговым значением, не освобождая его, он возвращается в состояние "Взаимодействие ".
  • Если пользователь освобождает список, инициируется запрос на обновление и переходит в состояние обновления .

пороговое значение после обновления

Визуально размер и непрозрачность значка составляют 100 %. В этом состоянии значок продолжает перемещаться вниз с помощью действия прокрутки, но больше не вращается.

Освежение

Когда пользователь освобождает визуализатор за пороговым значением, он находится в состоянии обновления .

При вводе этого состояния вызывается событие RefreshRequested . Это сигнал для запуска обновления содержимого приложения. Аргументы событий (RefreshRequestedEventArgs) содержат объект Deferral, к которому следует взять дескриптор в обработчике событий. Затем отложенное действие следует пометить как завершенное по завершении выполнения кода для обновления.

После завершения обновления визуализатор возвращается в состояние простоя .

Визуально значок возвращается обратно в пороговое положение и вращается на протяжении процесса обновления. Это вращение используется для отображения хода выполнения обновления и заменяется анимацией входящего содержимого.

Подглядывание

Когда пользователь тянет в направлении обновления из начальной позиции, в которой обновление не разрешено, визуализатор входит в состояние Предварительного просмотра. Как правило, это происходит, если элемент ScrollViewer не находится в начальной позиции, когда пользователь начинает перетаскивать.

  • Если пользователь освобождает элемент управления во время этого состояния, элемент управления возвращается в состояние простоя.

Направление тяги

По умолчанию пользователь оттягивает список сверху вниз, чтобы начать обновление. Если у вас есть список или сетка с другой ориентацией, следует изменить направление потягивания, чтобы контейнер обновления соответствовал.

Свойство PullDirection принимает одно из следующих значений RefreshPullDirection : BottomToTop, TopToBottom, RightToLeft или LeftToRight.

При изменении направления вытягивания начальная позиция индикатора хода выполнения визуализатора автоматически поворачивается, чтобы стрелка начиналась в правильной позиции в соответствии с направлением вытягивания. При необходимости можно изменить свойство RefreshVisualizer.Orientation , чтобы переопределить автоматическое поведение. В большинстве случаев рекомендуется оставить значение авто по умолчанию.

Реализация обновления по запросу

Приложение галерея WinUI 3 включает интерактивные примеры большинства элементов управления, функций и возможностей WinUI 3. Получение приложения из Microsoft Store или получение исходного кода на GitHub

Чтобы добавить функцию обновления путем оттягивания в список, нужно выполнить всего несколько действий.

  1. Оберните список в элемент управления RefreshContainer.
  2. Обработайте событие RefreshRequested , чтобы обновить содержимое.
  3. При необходимости инициируйте обновление путем вызова RequestRefresh (например, из кнопки).

Примечание.

Можно создать отдельный экземпляр RefreshVisualizer. Тем не менее мы рекомендуем переносить содержимое в RefreshContainer и использовать RefreshVisualizer, предоставляемый свойством RefreshContainer.Visualizer даже для сценариев без сенсорного ввода. В этой статье мы предполагаем, что визуализатор всегда получен из контейнера обновления.

Для удобства используйте RequestRefresh и RefreshRequested — члены контейнера обновления. refreshContainer.RequestRefresh()эквивалентноrefreshContainer.Visualizer.RequestRefresh(), и любой из них вызовет как событие RefreshContainer.RefreshRequested, так и события RefreshVisualizer.RefreshRequested.

Запрос на обновление

Контейнер обновления обрабатывает сенсорные взаимодействия, позволяя пользователю обновить содержимое с помощью сенсорного ввода. Мы рекомендуем реализовывать другие возможности для интерфейсов без сенсорного ввода, например, кнопку "Обновить" или управление голосом.

Чтобы инициировать обновление, вызовите метод RequestRefresh .

// See the Examples section for the full code.
private void RefreshButtonClick(object sender, RoutedEventArgs e)
{
    RefreshContainer.RequestRefresh();
}

При вызове RequestRefresh состояние визуализатора переходит непосредственно из простоя в обновление.

Обработка запроса на обновление

Чтобы по необходимости получать обновленное содержимое, обработайте событие RefreshRequested. Обработчике событий вам понадобится код вашего приложения, чтобы получить актуальное содержимое.

Аргументы события (RefreshRequestedEventArgs) содержат объект Deferral. Получите указатель на отсрочку в обработчике события. Затем отсрочку следует пометить как завершенную, когда код завершил выполнение обновления.

// See the Examples section for the full code.
private async void RefreshContainer_RefreshRequested(RefreshContainer sender, RefreshRequestedEventArgs args)
{
    // Respond to a request by performing a refresh and using the deferral object.
    using (var RefreshCompletionDeferral = args.GetDeferral())
    {
        // Do some async operation to refresh the content

         await FetchAndInsertItemsAsync(3);

        // The 'using' statement ensures the deferral is marked as complete.
        // Otherwise, you'd call
        // RefreshCompletionDeferral.Complete();
        // RefreshCompletionDeferral.Dispose();
    }
}

Реагирование на изменения состояния

При необходимости вы можете реагировать на изменения в состоянии визуализатора. Например, для предотвращения отправки нескольких запросов на обновление можно отключить кнопку "Обновить", во время обновления визуализатора.

// See the Examples section for the full code.
private void Visualizer_RefreshStateChanged(RefreshVisualizer sender, RefreshStateChangedEventArgs args)
{
    // Respond to visualizer state changes.
    // Disable the refresh button if the visualizer is refreshing.
    if (args.NewState == RefreshVisualizerState.Refreshing)
    {
        RefreshButton.IsEnabled = false;
    }
    else
    {
        RefreshButton.IsEnabled = true;
    }
}

Использование ScrollViewer в RefreshContainer

Примечание.

Содержимое RefreshContainer должно быть прокручиваемым элементом управления, например ScrollViewer, GridView, ListView и т. д. Установка содержимого в элемент управления, например Grid, приведет к неопределенному поведению.

В этом примере показано, как использовать функцию перетаскивания для обновления с просмотрщиком прокрутки.

<RefreshContainer>
    <ScrollViewer VerticalScrollMode="Enabled"
                  VerticalScrollBarVisibility="Auto"
                  HorizontalScrollBarVisibility="Auto">
 
        <!-- Scrollviewer content -->

    </ScrollViewer>
</RefreshContainer>

Добавление функции обновления путем оттягивания в ListView

В этом примере показано, как использовать функцию «потянуть для обновления» в списке.

<StackPanel Margin="0,40" Width="280">
    <CommandBar OverflowButtonVisibility="Collapsed">
        <AppBarButton x:Name="RefreshButton" Click="RefreshButtonClick"
                      Icon="Refresh" Label="Refresh"/>
        <CommandBar.Content>
            <TextBlock Text="List of items" 
                       Style="{StaticResource TitleTextBlockStyle}"
                       Margin="12,8"/>
        </CommandBar.Content>
    </CommandBar>

    <RefreshContainer x:Name="RefreshContainer">
        <ListView x:Name="ListView1" Height="400">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:ListItemData">
                    <Grid Height="80">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <TextBlock Text="{x:Bind Path=Header}"
                                   Style="{StaticResource SubtitleTextBlockStyle}"
                                   Grid.Row="0"/>
                        <TextBlock Text="{x:Bind Path=Date}"
                                   Style="{StaticResource CaptionTextBlockStyle}"
                                   Grid.Row="1"/>
                        <TextBlock Text="{x:Bind Path=Body}"
                                   Style="{StaticResource BodyTextBlockStyle}"
                                   Grid.Row="2"
                                   Margin="0,4,0,0" />
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </RefreshContainer>
</StackPanel>
public sealed partial class MainPage : Page
{
    public ObservableCollection<ListItemData> Items { get; set; } 
        = new ObservableCollection<ListItemData>();

    public MainPage()
    {
        this.InitializeComponent();

        Loaded += MainPage_Loaded;
        ListView1.ItemsSource = Items;
    }

    private async void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        Loaded -= MainPage_Loaded;
        RefreshContainer.RefreshRequested += RefreshContainer_RefreshRequested;
        RefreshContainer.Visualizer.RefreshStateChanged += Visualizer_RefreshStateChanged;

        // Add some initial content to the list.
        await FetchAndInsertItemsAsync(2);
    }

    private void RefreshButtonClick(object sender, RoutedEventArgs e)
    {
        RefreshContainer.RequestRefresh();
    }

    private async void RefreshContainer_RefreshRequested(RefreshContainer sender, RefreshRequestedEventArgs args)
    {
        // Respond to a request by performing a refresh and using the deferral object.
        using (var RefreshCompletionDeferral = args.GetDeferral())
        {
            // Do some async operation to refresh the content

            await FetchAndInsertItemsAsync(3);

            // The 'using' statement ensures the deferral is marked as complete.
            // Otherwise, you'd call
            // RefreshCompletionDeferral.Complete();
            // RefreshCompletionDeferral.Dispose();
        }
    }

    private void Visualizer_RefreshStateChanged(RefreshVisualizer sender, RefreshStateChangedEventArgs args)
    {
        // Respond to visualizer state changes.
        // Disable the refresh button if the visualizer is refreshing.
        if (args.NewState == RefreshVisualizerState.Refreshing)
        {
            RefreshButton.IsEnabled = false;
        }
        else
        {
            RefreshButton.IsEnabled = true;
        }
    }

    // App specific code to get fresh data.
    private async Task FetchAndInsertItemsAsync(int updateCount)
    {
        for (int i = 0; i < updateCount; ++i)
        {
            // Simulate delay while we go fetch new items.
            await Task.Delay(1000);
            Items.Insert(0, GetNextItem());
        }
    }

    private ListItemData GetNextItem()
    {
        return new ListItemData()
        {
            Header = "Header " + DateTime.Now.Second.ToString(),
            Date = DateTime.Now.ToLongDateString(),
            Body = DateTime.Now.ToLongTimeString()
        };
    }
}

public class ListItemData
{
    public string Header { get; set; }
    public string Date { get; set; }
    public string Body { get; set; }
}

UWP и WinUI 2

Внимание

Сведения и примеры, приведенные в этой статье, оптимизированы для приложений, использующих Windows App SDK и WinUI 3, но, как правило, применимы и к приложениям UWP, использующим WinUI 2. См. справочник по API UWP для конкретных сведений и примеров платформы.

В этом разделе содержатся сведения, необходимые для использования элемента управления в приложении UWP или WinUI 2.

Элементы управления обновления для приложений UWP включены в состав WinUI 2. Дополнительные сведения, включая инструкции по установке, см. в статье WinUI 2. API для этого элемента управления существуют в пространствах имен Windows.UI.Xaml.Controls (UWP) и Microsoft.UI.Xaml.Controls (WinUI).

Мы рекомендуем использовать последнюю версию WinUI 2 , чтобы получить самые актуальные стили, шаблоны и функции для всех элементов управления.

Чтобы использовать код в этой статье с WinUI 2, используйте псевдоним в XAML (мы используем muxc), чтобы представить API библиотеки пользовательского интерфейса Windows, включенные в проект. Дополнительные сведения см. в статье "Начало работы с WinUI 2 ".

xmlns:muxc="using:Microsoft.UI.Xaml.Controls"

<muxc:RefreshContainer />