// Apply two sourcemodifiers to the input source: One to provide resistance, one to stop motion public void SetupPullToRefreshBehavior( float pullToRefreshDistance) { // // Modifier 1: Cut DeltaY to a third as long as the InteractionTracker is not yet at the // pullRefreshDistance. // 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; // // Modifier 2: Zero the delta if we are past the pullRefreshDistance. (So we can't pan // past the pullRefreshDistance) // 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; // // Apply the modifiers to the source as a list // List <CompositionConditionalValue> modifierList = new List <CompositionConditionalValue>() { resistanceModifier, stoppingModifier }; _interactionSource.ConfigureDeltaPositionYModifiers(modifierList); }
private void ConfigureInteractionTracker() { _interactionSource = VisualInteractionSource.Create(_rootContainer); _interactionSource.ScaleSourceMode = InteractionSourceMode.EnabledWithInertia; _interactionSource.PositionXSourceMode = InteractionSourceMode.EnabledWithInertia; _tracker = InteractionTracker.CreateWithOwner(_compositor, this); _tracker.MinScale = 0.6f; _tracker.MaxScale = 5.0f; _tracker.MaxPosition = new Vector3((float)Root.ActualWidth * 1.5f, 0, 0); _tracker.MinPosition = _tracker.MaxPosition * -1; _tracker.ScaleInertiaDecayRate = 0.96f; _tracker.InteractionSources.Add(_interactionSource); var tracker = _tracker.GetReference(); // // Here's the trick: we take the scale output from the tracker, and convert it into a // value that represents Z. Then we bind it to the world container's Z position. // var scaleExpression = EF.Lerp(0, 1000, (1 - tracker.Scale) / (1 - tracker.MaxScale)); _worldContainer.StartAnimation("Offset.Z", scaleExpression); // // Bind the output of the tracker to the world container's XY position. // _worldContainer.StartAnimation("Offset.XY", -tracker.Position.XY); // // Scaling usually affects position. This depends on the center point of the scale. // But for our UI, we want don't scale to adjust the position (since we're using scale // to change Offset.Z). So to prevent scale from affecting position, we must always use // the top-left corner of the WorldContainer as the center point (note: we could also // use the tracker's negated position, since that's where WorldContainer is getting its // offset). // // Create input modifiers to override the center point value. // var centerpointXModifier = CompositionConditionalValue.Create(_compositor); var centerpointYModifier = CompositionConditionalValue.Create(_compositor); centerpointXModifier.Condition = _compositor.CreateExpressionAnimation("true"); centerpointXModifier.Value = _compositor.CreateExpressionAnimation("world.Offset.X"); centerpointXModifier.Value.SetReferenceParameter("world", _worldContainer); _interactionSource.ConfigureCenterPointXModifiers(new[] { centerpointXModifier }); _tracker.ConfigureCenterPointXInertiaModifiers(new[] { centerpointXModifier }); centerpointYModifier.Condition = _compositor.CreateExpressionAnimation("true"); centerpointYModifier.Value = _compositor.CreateExpressionAnimation("world.Offset.Y"); centerpointYModifier.Value.SetReferenceParameter("world", _worldContainer); _interactionSource.ConfigureCenterPointYModifiers(new[] { centerpointYModifier }); _tracker.ConfigureCenterPointYInertiaModifiers(new[] { centerpointYModifier }); }
private void MainPage_Loaded(object sender, RoutedEventArgs e) { ThumbnailList.ItemsSource = new List <Item> { new Item { Name = "Daren" }, new Item { Name = "Kendra" }, new Item { Name = "Gavin" }, new Item { Name = "Naia" }, new Item { Name = "Frodo" }, new Item { Name = "Stella" }, new Item { Name = "DJ" }, new Item { Name = "Stasch" } }; // InteractionTracker and VisualInteractionSource setup. _root = ElementCompositionPreview.GetElementVisual(Root); _contentPanelVisual = ElementCompositionPreview.GetElementVisual(ContentPanel); _compositor = _root.Compositor; _tracker = InteractionTracker.Create(_compositor); _interactionSource = VisualInteractionSource.Create(_root); _interactionSource.PositionYSourceMode = InteractionSourceMode.EnabledWithInertia; _interactionSource.PositionYChainingMode = InteractionChainingMode.Always; _tracker.InteractionSources.Add(_interactionSource); var 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); var resistanceModifier = CompositionConditionalValue.Create(_compositor); var resistanceCondition = _compositor.CreateExpressionAnimation( $"-tracker.Position.Y < {pullToRefreshDistance}"); resistanceCondition.SetReferenceParameter("tracker", _tracker); var resistanceAlternateValue = _compositor.CreateExpressionAnimation( "source.DeltaPosition.Y / 3"); resistanceAlternateValue.SetReferenceParameter("source", _interactionSource); resistanceModifier.Condition = resistanceCondition; resistanceModifier.Value = resistanceAlternateValue; var stoppingModifier = CompositionConditionalValue.Create(_compositor); var stoppingCondition = _compositor.CreateExpressionAnimation( $"-tracker.Position.Y >= {pullToRefreshDistance}"); stoppingCondition.SetReferenceParameter("tracker", _tracker); var stoppingAlternateValue = _compositor.CreateExpressionAnimation("0"); stoppingModifier.Condition = stoppingCondition; stoppingModifier.Value = stoppingAlternateValue; //Now add the 2 source modifiers to the InteractionTracker. var modifierList = new List <CompositionConditionalValue> { resistanceModifier, stoppingModifier }; _interactionSource.ConfigureDeltaPositionYModifiers(modifierList); //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); }