当向下滚动时,Groove将标题向上移动到可见区域之外,就像常规的ListView标题一样。当向上滚动时,它会立即将标题向下移动到可见区域,而不管当前的垂直滚动偏移量。标题似乎是ListView内容的一部分,因为滚动条包含标题。
如何在Windows 10 UWP应用程序中实现这一点?

发布于 2016-08-18 21:34:52
您可以通过利用ListView's内部的ScrollViewer's ViewChanged事件来完成此操作。
首先,您需要获取内部ScrollViewer。这是最简单的版本,但您可能希望使用众多VisualTreeHelper扩展中的一个来实现更安全、更容易的操作:
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var border = VisualTreeHelper.GetChild(MyListView, 0);
var scrollviewer = VisualTreeHelper.GetChild(border, 0) as ScrollViewer;
scrollviewer.ViewChanged += Scrollviewer_ViewChanged;
}在EventHandler中,您可以根据滚动方向更改标题的可见性。
private void Scrollviewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
var sv = sender as ScrollViewer;
if (sv.VerticalOffset > _lastVerticalOffset)
{
MyHeader.Visibility = Visibility.Collapsed;
}
else
{
MyHeader.Visibility = Visibility.Visible;
}
}这是基本的想法。你可能不想添加一些平滑的动画,而不仅仅是改变可见性。
发布于 2016-08-23 19:24:36
在环顾四周并进行了一些实验之后,我现在可以回答我自己的问题了。
可以使用基于表达式的composition animation来调整标题相对于滚动的Y偏移量。这个想法是基于这个answer的。我在GitHub上准备了一个完整的工作示例。
动画是在ListView的SizeChanged事件中准备的:
ScrollViewer scrollViewer = null;
private double previousVerticalScrollOffset = 0.0;
private CompositionPropertySet scrollProperties;
private CompositionPropertySet animationProperties;
SizeChanged += (sender, args) =>
{
if (scrollProperties == null)
scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer);
var compositor = scrollProperties.Compositor;
if (animationProperties == null)
{
animationProperties = compositor.CreatePropertySet();
animationProperties.InsertScalar("OffsetY", 0.0f);
}
var expressionAnimation = compositor.CreateExpressionAnimation("animationProperties.OffsetY - ScrollingProperties.Translation.Y");
expressionAnimation.SetReferenceParameter("ScrollingProperties", scrollProperties);
expressionAnimation.SetReferenceParameter("animationProperties", animationProperties);
var headerVisual = ElementCompositionPreview.GetElementVisual((UIElement)Header);
headerVisual.StartAnimation("Offset.Y", expressionAnimation);
};animationProperties中的OffsetY变量将驱动标头的OffsetY属性的动画。在ScrollViewer的ViewChanged事件中更新OffsetY变量:
scrollViewer.ViewChanged += (sender, args) =>
{
float oldOffsetY = 0.0f;
animationProperties.TryGetScalar("OffsetY", out oldOffsetY);
var delta = scrollViewer.VerticalOffset - previousVerticalScrollOffset;
previousVerticalScrollOffset = scrollViewer.VerticalOffset;
var newOffsetY = oldOffsetY - (float)delta;
// Keep values within negativ header size and 0
FrameworkElement header = (FrameworkElement)Header;
newOffsetY = Math.Max((float)-header.ActualHeight, newOffsetY);
newOffsetY = Math.Min(0, newOffsetY);
if (oldOffsetY != newOffsetY)
animationProperties.InsertScalar("OffsetY", newOffsetY);
};虽然这样可以正确地设置动画,但标题不会堆叠在ListView项的顶部。因此,最后一块拼图是降低ListView的ItemsPanelTemplate的ZIndex:
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel Canvas.ZIndex="-1" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>这就是结果:

https://stackoverflow.com/questions/38985339
复制相似问题