/// <summary> /// Uses Composition API to get the UIElement and sets an ExpressionAnimation /// The ExpressionAnimation uses the height of the UIElement to calculate an opacity value /// for the Header as it is scrolling off-screen. The opacity reaches 0 when the Header /// is entirely scrolled off. /// </summary> /// <returns><c>true</c> if the assignment was successful; otherwise, <c>false</c>.</returns> private bool AssignAnimation() { StopAnimation(); // Confirm that Windows.UI.Xaml.Hosting.ElementCompositionPreview is available (Windows 10 10586 or later). if (!ApiInformation.IsMethodPresent("Windows.UI.Xaml.Hosting.ElementCompositionPreview", nameof(ElementCompositionPreview.GetScrollViewerManipulationPropertySet))) { // Just return true since it's not supported return(true); } if (AssociatedObject == null) { return(false); } if (_scrollViewer == null) { _scrollViewer = AssociatedObject as ScrollViewer ?? AssociatedObject.FindDescendant <ScrollViewer>(); } if (_scrollViewer == null) { return(false); } var listView = AssociatedObject as Windows.UI.Xaml.Controls.ListViewBase ?? AssociatedObject.FindDescendant <Windows.UI.Xaml.Controls.ListViewBase>(); if (listView != null && listView.ItemsPanelRoot != null) { Canvas.SetZIndex(listView.ItemsPanelRoot, -1); } if (_scrollProperties == null) { _scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(_scrollViewer); } if (_scrollProperties == null) { return(false); } // Implicit operation: Find the Header object of the control if it uses ListViewBase if (HeaderElement == null && listView != null) { HeaderElement = listView.Header as UIElement; } var headerElement = HeaderElement as FrameworkElement; if (headerElement == null || headerElement.RenderSize.Height == 0) { return(false); } if (_headerVisual == null) { _headerVisual = ElementCompositionPreview.GetElementVisual(headerElement); } if (_headerVisual == null) { return(false); } headerElement.SizeChanged -= ScrollHeader_SizeChanged; headerElement.SizeChanged += ScrollHeader_SizeChanged; _scrollViewer.GotFocus -= ScrollViewer_GotFocus; _scrollViewer.GotFocus += ScrollViewer_GotFocus; var compositor = _scrollProperties.Compositor; if (_animationProperties == null) { _animationProperties = compositor.CreatePropertySet(); _animationProperties.InsertScalar("OffsetY", 0.0f); } _previousVerticalScrollOffset = _scrollViewer.VerticalOffset; var propSetOffset = _animationProperties.GetReference().GetScalarProperty("OffsetY"); var scrollPropSet = _scrollProperties.GetSpecializedReference <ManipulationPropertySetReferenceNode>(); var expressionAnimation = ExpressionFunctions.Max(propSetOffset - scrollPropSet.Translation.Y, 0); _headerVisual.StartAnimation("Offset.Y", expressionAnimation); return(true); }
/// <summary> /// Uses Composition API to get the UIElement and sets an ExpressionAnimation /// The ExpressionAnimation uses the height of the UIElement to calculate an opacity value /// for the Header as it is scrolling off-screen. The opacity reaches 0 when the Header /// is entirely scrolled off. /// </summary> /// <returns><c>true</c> if the assignment was successful; otherwise, <c>false</c>.</returns> private bool AssignAnimation() { StopAnimation(); if (AssociatedObject == null) { return(false); } if (_scrollViewer == null) { _scrollViewer = AssociatedObject as ScrollViewer ?? AssociatedObject.FindDescendant <ScrollViewer>(); } if (_scrollViewer == null) { return(false); } var listView = AssociatedObject as Windows.UI.Xaml.Controls.ListViewBase ?? AssociatedObject.FindDescendant <Windows.UI.Xaml.Controls.ListViewBase>(); if (listView != null && listView.ItemsPanelRoot != null) { Canvas.SetZIndex(listView.ItemsPanelRoot, -1); } if (_scrollProperties == null) { _scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(_scrollViewer); } if (_scrollProperties == null) { return(false); } // Implicit operation: Find the Header object of the control if it uses ListViewBase if (HeaderElement == null && listView != null) { HeaderElement = listView.Header as UIElement; } var headerElement = HeaderElement as FrameworkElement; if (headerElement == null || headerElement.RenderSize.Height == 0) { return(false); } if (_headerVisual == null) { _headerVisual = ElementCompositionPreview.GetElementVisual(headerElement); } if (_headerVisual == null) { return(false); } _scrollViewer.ViewChanged -= ScrollViewer_ViewChanged; _scrollViewer.ViewChanged += ScrollViewer_ViewChanged; _scrollViewer.GotFocus -= ScrollViewer_GotFocus; _scrollViewer.GotFocus += ScrollViewer_GotFocus; headerElement.SizeChanged -= ScrollHeader_SizeChanged; headerElement.SizeChanged += ScrollHeader_SizeChanged; var compositor = _scrollProperties.Compositor; if (_animationProperties == null) { _animationProperties = compositor.CreatePropertySet(); _animationProperties.InsertScalar("OffsetY", 0.0f); } var propSetOffset = _animationProperties.GetReference().GetScalarProperty("OffsetY"); var scrollPropSet = _scrollProperties.GetSpecializedReference <ManipulationPropertySetReferenceNode>(); var expressionAnimation = ExpressionFunctions.Max(ExpressionFunctions.Min(propSetOffset, -scrollPropSet.Translation.Y), 0); _headerVisual.StartAnimation("Offset.Y", expressionAnimation); return(true); }
/// <summary> /// Uses Composition API to get the UIElement and sets an ExpressionAnimation /// The ExpressionAnimation uses the height of the UIElement to calculate an opacity value /// for the Header as it is scrolling off-screen. The opacity reaches 0 when the Header /// is entirely scrolled off. /// </summary> /// <returns><c>true</c> if the assignment was successful; otherwise, <c>false</c>.</returns> private bool AssignAnimation() { StopAnimation(); if (AssociatedObject == null) { return(false); } if (_scrollViewer == null) { _scrollViewer = AssociatedObject as ScrollViewer ?? AssociatedObject.FindDescendant <ScrollViewer>(); } if (_scrollViewer == null) { return(false); } var listView = AssociatedObject as ListViewBase ?? AssociatedObject.FindDescendant <ListViewBase>(); if (listView != null && listView.ItemsPanelRoot != null) { Canvas.SetZIndex(listView.ItemsPanelRoot, -1); } if (_scrollProperties == null) { _scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(_scrollViewer); } if (_scrollProperties == null) { return(false); } // Implicit operation: Find the Header object of the control if it uses ListViewBase if (HeaderElement == null && listView != null) { HeaderElement = listView.Header as UIElement; } var headerElement = HeaderElement as FrameworkElement; if (headerElement == null || headerElement.RenderSize.Height == 0) { return(false); } if (_headerVisual == null) { _headerVisual = ElementCompositionPreview.GetElementVisual(headerElement); } if (_headerVisual == null) { return(false); } headerElement.SizeChanged -= ScrollHeader_SizeChanged; headerElement.SizeChanged += ScrollHeader_SizeChanged; _scrollViewer.GotFocus -= ScrollViewer_GotFocus; _scrollViewer.GotFocus += ScrollViewer_GotFocus; var compositor = _scrollProperties.Compositor; if (_animationProperties == null) { _animationProperties = compositor.CreatePropertySet(); _animationProperties.InsertScalar("OffsetY", 0.0f); } var propSetOffset = _animationProperties.GetReference().GetScalarProperty("OffsetY"); var scrollPropSet = _scrollProperties.GetSpecializedReference <ManipulationPropertySetReferenceNode>(); var expressionAnimation = ExpressionFunctions.Max(propSetOffset - scrollPropSet.Translation.Y, 0); _headerVisual.StartAnimation("Offset.Y", expressionAnimation); // Mod: clip items panel below header var itemsPanel = listView.ItemsPanelRoot; if (itemsPanel == null) { return(true); } if (_itemsPanelVisual == null) { _itemsPanelVisual = ElementCompositionPreview.GetElementVisual(itemsPanel); _contentClip = compositor.CreateInsetClip(); _itemsPanelVisual.Clip = _contentClip; } var expressionClipAnimation = ExpressionFunctions.Max(-scrollPropSet.Translation.Y, 0); _contentClip.TopInset = (float)System.Math.Max(-_scrollViewer.VerticalOffset, 0); _contentClip.StartAnimation("TopInset", expressionClipAnimation); return(true); }