Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Dalam artikel ini, kami menyelami lebih dalam cara menggunakan fitur SourceModifier InteractionTracker dan menunjukkan penggunaannya dengan membuat kontrol pull-to-refresh kustom.
Prasyarat
Di sini, kami berasumsi bahwa Anda terbiasa dengan konsep yang dibahas dalam artikel ini:
- Animasi berbasis input
- Pengalaman manipulasi kustom dengan InteractionTracker
- Animasi berbasis relasi
Apa itu SourceModifier dan mengapa mereka berguna?
Seperti InertiaModifiers, SourceModifiers memberi Anda kontrol yang lebih presisi atas gerakan InteractionTracker. Tetapi tidak seperti InertiaModifiers yang menentukan gerakan setelah InteractionTracker memasuki inersia, SourceModifiers menentukan gerakan sementara InteractionTracker masih dalam keadaan berinteraksi. Dalam kasus ini, Anda menginginkan pengalaman yang berbeda dari "menempel pada jari" secara tradisional.
Contoh klasik dari ini adalah pengalaman tarik-untuk-memperbarui - ketika pengguna menarik daftar untuk memperbarui konten dan daftar menggulir dengan kecepatan yang sama dengan jari dan berhenti setelah jarak tertentu, gerakan akan terasa mendadak dan mekanis. Pengalaman yang lebih alami adalah memperkenalkan sensasi hambatan saat pengguna secara aktif berinteraksi dengan daftar. Nuansa kecil ini membantu membuat pengalaman pengguna akhir secara keseluruhan berinteraksi dengan daftar lebih dinamis dan menarik. Di bagian Contoh, kita masuk ke detail selengkapnya tentang cara membangun ini.
Ada 2 jenis Pengubah Sumber:
- DeltaPosition – adalah selisih antara posisi kerangka saat ini dan posisi kerangka jari sebelumnya selama interaksi geser sentuh. Pengubah sumber ini memungkinkan Anda memodifikasi posisi delta interaksi sebelum mengirimkannya untuk diproses lebih lanjut. Ini adalah parameter jenis Vector3 dan pengembang dapat memilih untuk memodifikasi salah satu atribut X atau Y atau Z dari posisi sebelum meneruskannya ke InteractionTracker.
- DeltaScale - adalah delta antara skala bingkai saat ini dan skala bingkai sebelumnya yang diterapkan selama interaksi zoom sentuh. Pengubah sumber ini memungkinkan Anda mengubah tingkat pembesaran interaksi. Ini adalah atribut jenis float yang dapat dimodifikasi pengembang sebelum meneruskannya ke InteractionTracker.
Ketika InteractionTracker dalam keadaan Berinteraksi, ia mengevaluasi setiap Pengubah Sumber yang ditetapkan untuknya dan menentukan apakah salah satu dari mereka berlaku. Ini berarti Anda dapat membuat dan menetapkan beberapa Pengubah Sumber ke InteractionTracker. Tetapi, saat menentukan masing-masing, Anda perlu melakukan hal berikut:
- Tentukan Kondisi – Ekspresi yang menentukan pernyataan kondisional saat Pengubah Sumber tertentu ini harus diterapkan.
- Tentukan DeltaPosition/DeltaScale – Ekspresi pengubah sumber yang mengubah DeltaPosition atau DeltaScale saat kondisi yang ditentukan di atas terpenuhi.
Example
Sekarang mari kita lihat bagaimana Anda dapat menggunakan Pengubah Sumber untuk membuat pengalaman pull-to-refresh kustom dengan kontrol WinUI XAML ListView yang ada. Kami akan menggunakan Kanvas sebagai "Panel Refresh" yang akan ditumpuk di atas XAML ListView untuk membangun pengalaman ini.
Untuk pengalaman pengguna akhir, kami ingin menciptakan efek "ketahanan" ketika pengguna secara aktif menggeser daftar (dengan sentuhan) dan berhenti setelah posisi melampaui titik tertentu.
Kode kerja untuk pengalaman ini dapat ditemukan di repo Windows UI Dev Labs di GitHub. Berikut adalah panduan langkah demi langkah dalam membangun pengalaman tersebut. Dalam kode markup XAML, Anda memiliki hal berikut:
<StackPanel Height="500" MaxHeight="500" x:Name="ContentPanel" HorizontalAlignment="Left" VerticalAlignment="Top" >
<Canvas Width="400" Height="100" x:Name="RefreshPanel" >
<Image x:Name="FirstGear" Source="ms-appx:///Assets/Loading.png" Width="20" Height="20" Canvas.Left="200" Canvas.Top="70"/>
</Canvas>
<ListView x:Name="ThumbnailList"
MaxWidth="400"
Height="500"
ScrollViewer.VerticalScrollMode="Enabled" ScrollViewer.IsScrollInertiaEnabled="False" ScrollViewer.IsVerticalScrollChainingEnabled="True" >
<ListView.ItemTemplate>
……
</ListView.ItemTemplate>
</ListView>
</StackPanel>
Karena ListView (ThumbnailList) adalah kontrol XAML yang sudah dapat digulir, pengguliran perlu dihubungkan ke induknya (ContentPanel) ketika mencapai item paling atas dan tidak dapat menggulir lagi. (ContentPanel adalah tempat Anda akan menerapkan Pengubah Sumber.) Agar hal ini terjadi, Anda perlu mengatur ScrollViewer.IsVerticalScrollChainingEnabled ke true dalam markup ListView. Anda juga perlu mengatur mode penautan pada VisualInteractionSource ke Always.
Anda perlu mengatur handler PointerPressedEvent dengan parameter handledEventsToo sebagai true. Tanpa opsi ini, PointerPressedEvent tidak akan ditautkan ke ContentPanel karena kontrol ListView akan menandai peristiwa tersebut sebagai ditangani dan tidak akan dikirim ke rantai visual.
//The PointerPressed handler needs to be added using AddHandler method with the //handledEventsToo boolean set to "true"
//instead of the XAML element's "PointerPressed=Window_PointerPressed",
//because the list view needs to chain PointerPressed handled events as well.
ContentPanel.AddHandler(PointerPressedEvent, new PointerEventHandler( Window_PointerPressed), true);
Sekarang, Anda siap untuk mengikat ini dengan InteractionTracker. Mulailah dengan menyiapkan InteractionTracker, VisualInteractionSource, dan Ekspresi yang akan memanfaatkan posisi InteractionTracker.
// InteractionTracker and VisualInteractionSource setup.
_root = ElementCompositionPreview.GetElementVisual(Root);
_compositor = _root.Compositor;
_tracker = InteractionTracker.Create(_compositor);
_interactionSource = VisualInteractionSource.Create(_root);
_interactionSource.PositionYSourceMode = InteractionSourceMode.EnabledWithInertia;
_interactionSource.PositionYChainingMode = InteractionChainingMode.Always;
_tracker.InteractionSources.Add(_interactionSource);
float refreshPanelHeight = (float)RefreshPanel.ActualHeight;
_tracker.MaxPosition = new Vector3((float)Root.ActualWidth, 0, 0);
_tracker.MinPosition = new Vector3(-(float)Root.ActualWidth, -refreshPanelHeight, 0);
// Use the Tacker's Position (negated) to apply to the Offset of the Image.
// The -{refreshPanelHeight} is to hide the refresh panel
m_positionExpression = _compositor.CreateExpressionAnimation($"-tracker.Position.Y - {refreshPanelHeight} ");
m_positionExpression.SetReferenceParameter("tracker", _tracker);
_contentPanelVisual.StartAnimation("Offset.Y", m_positionExpression);
Dengan pengaturan ini, panel penyegaran berada di luar viewport dalam posisi awalnya dan semua yang dilihat pengguna adalah listView. Ketika panning mencapai ContentPanel, acara PointerPressed akan dipicu, di mana Anda meminta Sistem untuk menggunakan InteractionTracker untuk menggerakkan pengalaman manipulasi.
private void Window_PointerPressed(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Touch) {
// Tell the system to use the gestures from this pointer point (if it can).
_interactionSource.TryRedirectForManipulation(e.GetCurrentPoint(null));
}
}
Nota
Jika penautan peristiwa Yang Ditangani tidak diperlukan, menambahkan penangan PointerPressedEvent dapat dilakukan langsung melalui markup XAML menggunakan atribut (PointerPressed="Window_PointerPressed").
Langkah selanjutnya adalah menyiapkan pengubah sumber. Anda akan menggunakan 2 pengubah sumber untuk mendapatkan perilaku ini; Perlawanan dan Berhenti.
- Resistance – Gerakkan DeltaPosition.Y dengan kecepatan setengah hingga mencapai tinggi RefreshPanel.
CompositionConditionalValue resistanceModifier = CompositionConditionalValue.Create (_compositor);
ExpressionAnimation resistanceCondition = _compositor.CreateExpressionAnimation(
$"-tracker.Position.Y < {pullToRefreshDistance}");
resistanceCondition.SetReferenceParameter("tracker", _tracker);
ExpressionAnimation resistanceAlternateValue = _compositor.CreateExpressionAnimation(
"source.DeltaPosition.Y / 3");
resistanceAlternateValue.SetReferenceParameter("source", _interactionSource);
resistanceModifier.Condition = resistanceCondition;
resistanceModifier.Value = resistanceAlternateValue;
- Berhenti – Berhenti bergerak setelah seluruh RefreshPanel berada di layar.
CompositionConditionalValue stoppingModifier = CompositionConditionalValue.Create (_compositor);
ExpressionAnimation stoppingCondition = _compositor.CreateExpressionAnimation(
$"-tracker.Position.Y >= {pullToRefreshDistance}");
stoppingCondition.SetReferenceParameter("tracker", _tracker);
ExpressionAnimation stoppingAlternateValue = _compositor.CreateExpressionAnimation("0");
stoppingModifier.Condition = stoppingCondition;
stoppingModifier.Value = stoppingAlternateValue;
Now add the 2 source modifiers to the InteractionTracker.
List<CompositionConditionalValue> modifierList = new List<CompositionConditionalValue>()
{ resistanceModifier, stoppingModifier };
_interactionSource.ConfigureDeltaPositionYModifiers(modifierList);
Diagram ini memberikan visualisasi penyiapan SourceModifiers.
Sekarang dengan SourceModifiers, Anda akan melihat ketika menggeser ListView ke atas dan mencapai item paling atas, panel penyegar ditarik ke bawah dengan setengah kecepatan geseran hingga mencapai tinggi panel penyegar dan kemudian berhenti bergerak.
Dalam sampel lengkap, animasi keyframe digunakan untuk memutar ikon selama interaksi di kanvas RefreshPanel. Konten apa pun dapat digunakan di tempatnya atau menggunakan posisi InteractionTracker untuk mendorong animasi tersebut secara terpisah.
Windows developer