Add a quick return header control

This commit is contained in:
Patrick Dehne 2016-08-23 17:32:45 +02:00
Родитель b9313ada30
Коммит 1f87e720ae
8 изменённых файлов: 324 добавлений и 0 удалений

Просмотреть файл

@ -239,6 +239,7 @@
<Content Include="SamplePages\ImageEx\ImageEx.png" />
<Content Include="SamplePages\Offset\OffsetBehavior.png" />
<Content Include="SamplePages\PullToRefreshListView\PullToRefreshListView.png" />
<Content Include="SamplePages\QuickReturnHeader\QuickReturnHeader.png" />
<Content Include="SamplePages\RadialGauge\RadialGauge.png" />
<Content Include="SamplePages\RangeSelector\RangeSelector.png" />
<Content Include="SamplePages\AdaptiveGridView\AdaptiveGridView.png" />
@ -289,6 +290,7 @@
<Content Include="SamplePages\Scale\ScaleBehaviorXaml.bind" />
<Content Include="SamplePages\Rotate\RotateBehaviorXaml.bind" />
<Content Include="SamplePages\BladeControl\BladeCode.bind" />
<Content Include="SamplePages\QuickReturnHeader\QuickReturnHeaderCode.bind" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
@ -322,6 +324,9 @@
<Compile Include="SamplePages\Blur\BlurBehaviorPage.xaml.cs">
<DependentUpon>BlurBehaviorPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\QuickReturnHeader\QuickReturnHeaderPage.xaml.cs">
<DependentUpon>QuickReturnHeaderPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\RotatorTile\RotatorTilePage.xaml.cs">
<DependentUpon>RotatorTilePage.xaml</DependentUpon>
</Compile>
@ -422,6 +427,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="SamplePages\QuickReturnHeader\QuickReturnHeaderPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="SamplePages\RotatorTile\RotatorTilePage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.2 KiB

Просмотреть файл

@ -0,0 +1,31 @@
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.QuickReturnHeaderPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:models="using:Microsoft.Toolkit.Uwp.SampleApp.Models"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView Name="listView" ItemsSource="{x:Bind _items, Mode=OneWay}">
<ListView.Header>
<controls:QuickReturnHeader TargetListView="{x:Bind listView}" IsQuickReturnEnabled="@[Enabled:Bool:True]">
<StackPanel Padding="12" Background="#F0F0F0">
<TextBlock Text="Header 1" />
<TextBlock Text="Header 2" />
<TextBlock Text="Header 3" />
<TextBlock Text="Header 4" />
<TextBlock Text="Header 5" />
<TextBlock Text="Header 6" />
</StackPanel>
</controls:QuickReturnHeader>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Item">
<TextBlock Text="{x:Bind Title}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,31 @@
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.QuickReturnHeaderPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:models="using:Microsoft.Toolkit.Uwp.SampleApp.Models"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView Name="listView" ItemsSource="{x:Bind _items, Mode=OneWay}">
<ListView.Header>
<controls:QuickReturnHeader TargetListView="{x:Bind listView}" IsQuickReturnEnabled="{Binding Enabled.Value}">
<StackPanel Padding="12" Background="#F0F0F0">
<TextBlock Text="Header 1" />
<TextBlock Text="Header 2" />
<TextBlock Text="Header 3" />
<TextBlock Text="Header 4" />
<TextBlock Text="Header 5" />
<TextBlock Text="Header 6" />
</StackPanel>
</controls:QuickReturnHeader>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Item">
<TextBlock Text="{x:Bind Title}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,58 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.ObjectModel;
using Microsoft.Toolkit.Uwp.SampleApp.Models;
using Microsoft.Toolkit.Uwp.UI.Controls;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
public sealed partial class QuickReturnHeaderPage
{
private ObservableCollection<Item> _items;
public QuickReturnHeaderPage()
{
this.InitializeComponent();
ObservableCollection<Item> items = new ObservableCollection<Item>();
for (var i = 0; i < 500; i++)
{
items.Add(new Item() { Title = "Item " + i });
}
_items = items;
}
/// <summary>
/// Called on navigating to the QuickReturnHeader sample page.
/// </summary>
/// <param name="e">
/// The navigation event arguments.
/// </param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
var propertyDesc = e.Parameter as PropertyDescriptor;
if (propertyDesc != null)
{
DataContext = propertyDesc.Expando;
}
}
}
}

Просмотреть файл

@ -82,6 +82,14 @@
"CodeUrl": "https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/BladeControl",
"XamlCodeFile": "BladeCode.bind",
"Icon": "/SamplePages/BladeControl/Blade.png"
},
{
"Name": "QuickReturnHeader",
"Type": "QuickReturnHeaderPage",
"About": "A UI control that works as a quick return ListView header.",
"CodeUrl": "https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/QuickReturnHeader",
"XamlCodeFile": "QuickReturnHeaderCode.bind",
"Icon": "/SamplePages/QuickReturnHeader/QuickReturnHeader.png"
}
]
},

Просмотреть файл

@ -68,6 +68,7 @@
<Compile Include="ImageEx\ImageEx.Members.cs" />
<Compile Include="ImageEx\ImageEx.Placeholder.cs" />
<Compile Include="ImageEx\ImageEx.Source.cs" />
<Compile Include="QuickReturnHeader\QuickReturnHeader.cs" />
<Compile Include="RotatorTile\RotatorTile.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PullToRefreshListView\PullToRefreshListView.cs" />

Просмотреть файл

@ -0,0 +1,186 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Hosting;
using Windows.UI.Xaml.Media;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// Quick return header control to be used with ListViews
/// </summary>
public class QuickReturnHeader : ContentControl
{
public QuickReturnHeader()
{
HorizontalContentAlignment = HorizontalAlignment.Stretch;
}
/// <summary>
/// Identifies the <see cref="IsQuickReturnEnabled"/> property.
/// </summary>
public static readonly DependencyProperty IsQuickReturnEnabledProperty =
DependencyProperty.Register("IsQuickReturnEnabled", typeof(bool), typeof(QuickReturnHeader), new PropertyMetadata(true, OnIsQuickReturnEnabledChanged));
/// <summary>
/// Gets or sets a value indicating whether the quick return header is enabled.
/// If true the quick return behavior is used.
/// If false regular header behavior is used.
/// Default is true.
/// </summary>
public bool IsQuickReturnEnabled
{
get { return (bool)GetValue(IsQuickReturnEnabledProperty); }
set { SetValue(IsQuickReturnEnabledProperty, value); }
}
/// <summary>
/// Gets or sets the ListView this header belongs to
/// </summary>
public ListView TargetListView { get; set; }
protected override void OnApplyTemplate()
{
if (TargetListView != null)
{
scrollViewer = GetScrollViewer(TargetListView);
// Place items below header
var panel = TargetListView.ItemsPanelRoot;
Canvas.SetZIndex(panel, -1);
}
if (scrollViewer != null)
{
scrollViewer.ViewChanged += (sender, args) =>
{
if (animationProperties != null)
{
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)TargetListView.Header;
newOffsetY = Math.Max((float)-header.ActualHeight, newOffsetY);
newOffsetY = Math.Min(0, newOffsetY);
if (oldOffsetY != newOffsetY)
{
animationProperties.InsertScalar("OffsetY", newOffsetY);
}
}
};
}
SizeChanged += (sender, args) =>
{
if (TargetListView != null)
{
if (IsQuickReturnEnabled)
{
StartAnimation();
}
}
};
}
private static ScrollViewer GetScrollViewer(DependencyObject o)
{
if (o is ScrollViewer)
{
return o as ScrollViewer;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++)
{
var child = VisualTreeHelper.GetChild(o, i);
var result = GetScrollViewer(child);
if (result != null)
{
return result;
}
}
return null;
}
private static void OnIsQuickReturnEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var me = d as QuickReturnHeader;
if (me.IsQuickReturnEnabled)
{
me.StartAnimation();
}
else
{
me.StopAnimation();
}
}
private void StartAnimation()
{
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);
headerVisual = ElementCompositionPreview.GetElementVisual((UIElement)TargetListView.Header);
if (headerVisual != null && IsQuickReturnEnabled)
{
headerVisual.StartAnimation("Offset.Y", expressionAnimation);
}
}
private void StopAnimation()
{
if (headerVisual != null)
{
headerVisual.StopAnimation("Offset.Y");
animationProperties.InsertScalar("OffsetY", 0.0f);
var offset = headerVisual.Offset;
offset.Y = 0.0f;
headerVisual.Offset = offset;
}
}
private ScrollViewer scrollViewer;
private double previousVerticalScrollOffset;
private CompositionPropertySet scrollProperties;
private CompositionPropertySet animationProperties;
private Visual headerVisual;
}
}