Freigeben über


Aktualisierung durch Ziehen mit Quellmodifizierern

In diesem Artikel erfahren Sie, wie Sie das SourceModifier-Feature eines InteractionTracker-Elements verwenden und dessen Verwendung demonstrieren, indem sie ein benutzerdefiniertes Pull-to-Refresh-Steuerelement erstellen.

Voraussetzungen

Hier wird davon ausgegangen, dass Sie mit den in den folgenden Artikeln erläuterten Konzepten vertraut sind:

Was ist ein SourceModifier und warum sind sie nützlich?

Wie InertiaModifiers bieten SourceModifiers Ihnen eine feinere Kornkontrolle über die Bewegung eines InteractionTrackers. Im Gegensatz zu InertiaModifiern, die die Bewegung definieren, nachdem InteractionTracker in die Inertia wechselt, definieren SourceModifier die Bewegung, während InteractionTracker sich noch im Interaktionszustand befindet. In diesen Fällen möchten Sie eine andere Erfahrung als die traditionelle "Mit dem Finger halten".

Ein klassisches Beispiel dafür ist die Pull-to-Refresh-Erfahrung – wenn der Benutzer die Liste zieht, um den Inhalt zu aktualisieren, und die Listenverschiebungen mit der gleichen Geschwindigkeit wie der Finger und stoppt nach einer bestimmten Entfernung, würde die Bewegung abrupt und mechanisch wirken. Eine natürlichere Erfahrung wäre die Einführung eines Widerstandsgefühls, während der Benutzer aktiv mit der Liste interagiert. Diese kleine Nuance trägt dazu bei, die Benutzerfreundlichkeit insgesamt mit einer Liste dynamischer und ansprechender zu gestalten. Im Abschnitt "Beispiel" erfahren Sie mehr darüber, wie Sie dies erstellen.

Es gibt zwei Arten von Quellmodifizierern:

  • DeltaPosition – ist das Delta zwischen der aktuellen Frameposition und der vorherigen Frameposition des Fingers während der Touchverschiebungsinteraktion. Mit diesem Quellmodifizierer können Sie die Deltaposition der Interaktion ändern, bevor Sie sie zur weiteren Verarbeitung senden. Dies ist ein Vector3-Typparameter, und der Entwickler kann eine der X- oder Y- oder Z-Attribute der Position ändern, bevor sie an den InteractionTracker übergeben wird.
  • DeltaScale – ist das Delta zwischen der aktuellen Frameskala und der vorherigen Frameskala, die während der Touchzoominteraktion angewendet wurde. Mit diesem Quellmodifizierer können Sie den Zoomfaktor der Interaktion ändern. Dies ist ein Float-Typattribut, das der Entwickler ändern kann, bevor er es an den InteractionTracker übergibt.

Wenn InteractionTracker sich in seinem Interaktionszustand befindet, wertet er jeden der ihm zugewiesenen Quellmodifizierer aus und bestimmt, ob eine dieser Modifizierer zutrifft. Dies bedeutet, dass Sie mehrere Quellmodifizierer erstellen und einem InteractionTracker zuweisen können. Beim Definieren der einzelnen Schritte müssen Sie jedoch folgendes tun:

  1. Definieren Sie die Bedingung – ein Ausdruck, der die bedingte Anweisung definiert, wenn dieser spezifische Quellmodifizierer angewendet werden soll.
  2. Definieren Sie die DeltaPosition/DeltaScale – Der Quellmodifiziererausdruck, der die DeltaPosition oder DeltaScale ändert, wenn die oben definierte Bedingung erfüllt ist.

Beispiel

Sehen wir uns nun an, wie Sie mithilfe von Quellmodifizierern eine benutzerdefinierte Aktualisierungserfahrung mit pull-to-refresh mit einem vorhandenen XAML ListView-Steuerelement erstellen können. Wir verwenden eine Canvas als "Aktualisierungsbereich", die über einer XAML-ListView gestapelt wird, um diese Erfahrung zu erstellen.

Für die Endbenutzererfahrung möchten wir die Wirkung von "Widerstand" schaffen, da der Benutzer die Liste (mit Toucheingabe) aktiv verschiebt und die Verschiebung beenden soll, nachdem die Position einen bestimmten Punkt überschreitet.

Liste mit Pull-to-Refresh

Der funktionierende Code für diese Erfahrung finden Sie im Window UI Dev Labs-Repository auf GitHub. Hier ist der schrittweise Schritt für Schritt durch die Erstellung dieser Erfahrung. Im XAML-Markupcode haben Sie Folgendes:

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

Da listView (ThumbnailList) ein XAML-Steuerelement ist, das bereits scrollt, muss der Bildlauf bis zum übergeordneten Element (ContentPanel) verkettet werden, wenn es das oberste Element erreicht und nicht mehr scrollen kann. (ContentPanel ist der Ort, an dem Sie die Quellmodifizierer anwenden.) Dazu müssen Sie ScrollViewer.IsVerticalScrollChainingEnabled im ListView-Markup auf "true " festlegen. Außerdem müssen Sie den Verkettungsmodus in VisualInteractionSource auf Always festlegen.

Sie müssen den PointerPressedEvent-Handler mit dem parameter handledEventsToo als true festlegen. Ohne diese Option wird pointerPressedEvent nicht an das ContentPanel verkettet, da das ListView-Steuerelement diese Ereignisse als behandelt markiert und nicht an die visuelle Kette gesendet wird.

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

Jetzt können Sie dies mit InteractionTracker verknüpfen. Richten Sie zunächst InteractionTracker, die VisualInteractionSource und den Ausdruck ein, der die Position von InteractionTracker nutzt.

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

Bei dieser Einrichtung befindet sich der Aktualisierungsbereich außerhalb des Viewports in seiner Startposition, und alle Benutzer sehen die ListView, wenn die Verschiebung das ContentPanel erreicht, wird das PointerPressed-Ereignis ausgelöst, in dem Sie das System auffordern, InteractionTracker zu verwenden, um die Manipulationserfahrung zu steuern.

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

Hinweis

Wenn das Verketten von Handled-Ereignissen nicht erforderlich ist, kann das Hinzufügen von PointerPressedEvent-Handlern mithilfe des Attributs (PointerPressed="Window_PointerPressed") direkt über XAML-Markup erfolgen.

Der nächste Schritt besteht darin, die Quellmodifizierer einzurichten. Sie verwenden zwei Quellmodifizierer, um dieses Verhalten zu erhalten. Widerstand und Stopp.

  • Widerstand – Bewegen Sie die DeltaPosition.Y bei der Hälfte der Geschwindigkeit, bis sie die Höhe des RefreshPanel erreicht.
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;
  • Stop – Beenden Sie das Verschieben, nachdem sich das gesamte RefreshPanel auf dem Bildschirm befindet.
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);

Dieses Diagramm gibt eine Visualisierung des SourceModifiers-Setups.

Verschiebungsdiagramm

Jetzt mit den SourceModifiern werden Sie feststellen, wenn Sie die ListView nach unten verschieben und das oberste Element erreichen, wird der Aktualisierungsbereich in halbem Tempo der Verschiebung nach unten gezogen, bis es die RefreshPanel-Höhe erreicht und dann nicht mehr bewegt wird.

Im vollständigen Beispiel wird eine Keyframeanimation verwendet, um während der Interaktion im RefreshPanel-Zeichenbereich ein Symbol zu drehen. Jeder Inhalt kann an seinem Ort verwendet werden oder die Position von InteractionTracker nutzen, um diese Animation separat zu steuern.