Tarik untuk menyegarkan

Pull-to-refresh memungkinkan pengguna menarik ke bawah daftar data menggunakan sentuhan untuk mengambil lebih banyak data. Pull-to-refresh banyak digunakan pada perangkat dengan layar sentuh. Anda dapat menggunakan API yang ditampilkan di sini untuk menerapkan pull-to-refresh di aplikasi Anda.

gif pull-to-refresh

Apakah ini kontrol yang tepat?

Gunakan pull-to-refresh saat Anda memiliki daftar atau kisi data yang mungkin ingin di-refresh pengguna secara teratur, dan aplikasi Anda kemungkinan akan berjalan di perangkat touch-first.

Anda juga dapat menggunakan RefreshVisualizer untuk membuat pengalaman refresh konsisten yang dipanggil dengan cara lain, seperti dengan tombol refresh.

Menyegarkan kontrol

Pull-to-refresh diaktifkan oleh 2 kontrol.

  • RefreshContainer - ContentControl yang menyediakan pembungkus untuk pengalaman pull-to-refresh. Ini menangani interaksi sentuh dan mengelola status visualizer refresh internalnya.
  • RefreshVisualizer - merangkum visualisasi refresh yang dijelaskan di bagian berikutnya.

Kontrol utama adalah RefreshContainer, yang Anda tempatkan sebagai pembungkus di sekitar konten yang ditarik pengguna untuk memicu refresh. RefreshContainer hanya berfungsi dengan sentuhan, jadi kami sarankan Anda juga memiliki tombol refresh yang tersedia untuk pengguna yang tidak memiliki antarmuka sentuh. Anda dapat memosisikan tombol refresh di lokasi yang sesuai di aplikasi, baik di bilah perintah atau di lokasi yang dekat dengan permukaan yang sedang disegarkan.

Merefresh visualisasi

Visualisasi refresh default adalah spinner kemajuan melingkar yang digunakan untuk berkomunikasi ketika refresh akan terjadi dan kemajuan refresh setelah dimulai. Visualizer refresh memiliki 5 status.

Jarak pengguna perlu menarik ke bawah daftar untuk memulai refresh disebut ambang batas. Status visualizer ditentukan oleh status penarikan karena berkaitan dengan ambang batas ini. Nilai yang mungkin terkandung dalam enumerasi RefreshVisualizerState .

Idle

Status default penvisualisasi adalah Diam. Pengguna tidak berinteraksi dengan RefreshContainer melalui sentuhan, dan tidak ada refresh yang sedang berlangsung.

Secara visual, tidak ada bukti dari visualizer refresh.

Berinteraksi

Saat pengguna menarik daftar ke arah yang ditentukan oleh properti PullDirection, dan sebelum ambang tercapai, visualizer berada dalam status Berinteraksi .

  • Jika pengguna merilis kontrol saat dalam status ini, kontrol akan kembali ke Diam.

    pre-threshold pull-to-refresh

    Secara visual, ikon ditampilkan sebagai dinonaktifkan (opasitas 60%). Selain itu, ikon memutar satu rotasi penuh dengan tindakan gulir.

  • Jika pengguna menarik daftar melewati ambang batas, visualizer beralih dari Berinteraksi keTertunda.

    pull-to-refresh di ambang

    Secara visual, ikon beralih ke opasitas 100% dan pulsa dalam ukuran hingga 150% dan kemudian kembali ke ukuran 100% selama transisi.

Sedang diproses

Ketika pengguna telah menarik daftar melewati ambang batas, visualizer berada dalam status Tertunda .

  • Jika pengguna memindahkan daftar kembali ke atas ambang tanpa merilisnya, daftar akan kembali ke status Berinteraksi .
  • Jika pengguna merilis daftar, permintaan refresh dimulai dan bertransisi ke status Refresh .

pull-to-refresh pasca-ambang

Secara visual, ikonnya adalah 100% dalam ukuran dan opasitas. Dalam keadaan ini, ikon terus bergerak ke bawah dengan tindakan gulir tetapi tidak lagi berputar.

Me-refresh

Saat pengguna merilis visualiser melewati ambang batas, visualiser berada dalam status Refresh .

Ketika status ini dimasukkan, peristiwa RefreshRequested dinaikkan . Ini adalah sinyal untuk memulai refresh konten aplikasi. Argumen peristiwa (RefreshRequestedEventArgs) berisi objek Deferral , yang harus Anda tangani di penanganan aktivitas. Kemudian, Anda harus menandai penundaan sebagai selesai ketika kode Anda untuk melakukan refresh telah selesai.

Setelah refresh selesai, visualizer kembali ke status Menganggur .

Secara visual, ikon menetap kembali ke lokasi ambang dan berputar selama durasi refresh. Pemintalan ini digunakan untuk menunjukkan kemajuan refresh dan digantikan oleh animasi konten masuk.

Mengintip

Saat pengguna menarik arah refresh dari posisi awal di mana refresh tidak diizinkan, visualizer memasuki status Mengintip . Ini biasanya terjadi ketika ScrollViewer tidak berada di posisi 0 ketika pengguna mulai menarik.

  • Jika pengguna merilis kontrol saat dalam status ini, kontrol akan kembali ke Diam.

Arah penarikan

Secara default, pengguna menarik daftar dari atas ke bawah untuk memulai refresh. Jika Anda memiliki daftar atau kisi dengan orientasi yang berbeda, Anda harus mengubah arah tarik kontainer refresh agar sesuai.

Properti PullDirection mengambil salah satu nilai RefreshPullDirection ini: BottomToTop, TopToBottom, RightToLeft, atau LeftToRight.

Saat Anda mengubah arah penarikan, posisi awal pemintal kemajuan visualizer secara otomatis berputar sehingga panah dimulai dalam posisi yang sesuai untuk arah penarikan. Jika diperlukan, Anda dapat mengubah properti RefreshVisualizer.Orientation untuk mengambil alih perilaku otomatis. Dalam kebanyakan kasus, sebaiknya tinggalkan nilai default Otomatis.

UWP dan WinUI 2

Penting

Informasi dan contoh dalam artikel ini dioptimalkan untuk aplikasi yang menggunakan SDK Aplikasi Windows dan WinUI 3, tetapi umumnya berlaku untuk aplikasi UWP yang menggunakan WinUI 2. Lihat referensi API UWP untuk informasi dan contoh spesifik platform.

Bagian ini berisi informasi yang Anda butuhkan untuk menggunakan kontrol di aplikasi UWP atau WinUI 2.

Kontrol refresh untuk aplikasi UWP disertakan sebagai bagian dari Windows UI Library 2. Untuk informasi selengkapnya, termasuk instruksi penginstalan, lihat Pustaka Windows UI. API untuk kontrol ini ada di namespace Windows.UI.Xaml.Controls (UWP) dan Microsoft.UI.Xaml.Controls (WinUI).

Sebaiknya gunakan WinUI 2 terbaru untuk mendapatkan gaya, templat, dan fitur terbaru untuk semua kontrol.

Untuk menggunakan kode dalam artikel ini dengan WinUI 2, gunakan alias di XAML (kami menggunakan muxc) untuk mewakili API Pustaka Windows UI yang disertakan dalam proyek Anda. Lihat Mulai menggunakan WinUI 2 untuk informasi selengkapnya.

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

<muxc:RefreshContainer />

Menerapkan pull-to-refresh

Aplikasi WinUI 3 Gallery mencakup contoh interaktif sebagian besar kontrol, fitur, dan fungsi WinUI 3. Dapatkan aplikasi dari Microsoft Store atau dapatkan kode sumber di GitHub

Untuk menambahkan fungsionalitas pull-to-refresh ke daftar hanya memerlukan beberapa langkah.

  1. Bungkus daftar Anda dalam kontrol RefreshContainer .
  2. Tangani peristiwa RefreshRequested untuk me-refresh konten Anda.
  3. Secara opsional, mulai refresh dengan memanggil RequestRefresh (misalnya, dari klik tombol).

Catatan

Anda dapat membuat instans RefreshVisualizer sendiri. Namun, kami sarankan Anda membungkus konten Anda dalam RefreshContainer dan menggunakan RefreshVisualizer yang disediakan oleh properti RefreshContainer.Visualizer, bahkan untuk skenario non-sentuh. Dalam artikel ini, kami berasumsi bahwa visualizer selalu diperoleh dari kontainer refresh.

Selain itu, gunakan anggota RequestRefresh dan RefreshRequested kontainer refresh untuk kenyamanan. refreshContainer.RequestRefresh() setara refreshContainer.Visualizer.RequestRefresh()dengan , dan akan meningkatkan peristiwa RefreshContainer.RefreshRequested dan peristiwa RefreshVisualizer.RefreshRequested.

Meminta refresh

Kontainer refresh menangani interaksi sentuh untuk memungkinkan pengguna menyegarkan konten melalui sentuhan. Kami menyarankan agar Anda menyediakan keunggulan lain untuk antarmuka non-sentuh, seperti tombol refresh atau kontrol suara.

Untuk memulai refresh, panggil metode RequestRefresh .

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

Saat Anda memanggil RequestRefresh, status visualizer langsung dari Menganggur ke Refresh.

Menangani permintaan refresh

Untuk mendapatkan konten baru saat diperlukan, tangani peristiwa RefreshRequested. Di penanganan aktivitas, Anda memerlukan kode khusus untuk aplikasi Anda untuk mendapatkan konten baru.

Argumen peristiwa (RefreshRequestedEventArgs) berisi objek Deferral . Dapatkan handel ke penahanan di penanganan aktivitas. Kemudian, tandai penundaan sebagai selesai saat kode Anda untuk melakukan refresh telah selesai.

// 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();
    }
}

Merespons perubahan status

Anda dapat merespons perubahan dalam status visualizer, jika diperlukan. Misalnya, untuk mencegah beberapa permintaan refresh, Anda dapat menonaktifkan tombol refresh saat visualizer di-refresh.

// 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;
    }
}

Menggunakan ScrollViewer di RefreshContainer

Catatan

Konten RefreshContainer harus merupakan kontrol yang dapat digulir, seperti ScrollViewer, GridView, ListView, dll. Mengatur Konten ke kontrol seperti Grid akan mengakibatkan perilaku yang tidak terdefinisi.

Contoh ini menunjukkan cara menggunakan pull-to-refresh dengan penampil gulir.

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

    </ScrollViewer>
</RefreshContainer>

Menambahkan pull-to-refresh ke ListView

Contoh ini memperlihatkan cara menggunakan pull-to-refresh dengan tampilan daftar.

<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; }
}

Dapatkan kode sampel