UWP uses the Composition API to achieve ceiling (1) and uwpcomposition
A few days ago, I needed to achieve ceiling suction in UWP, so I found some articles on the Internet:
Ceiling method-one of the methods to achieve top ceiling of toolbar in UWP
Move the navigation bar to the top of the UWP page
It is found that most of the methods previously implemented are to control the height change of the Header of ListViewBase, or to create a ScrollViewer to place ListViewBase in it. After testing, both methods have problems. So I want to try to use the Composition API to achieve the ceiling effect.
First, let's take a look at what Composition API is.
Windows. UI. Composition is a declarative retention mode API that can be called from any universal Windows platform (UWP) application, so that you can directly create compositing objects, animations, and effects in the application. This API is a powerful complement to existing frameworks such as XAML, providing UWP application developers with a familiar C # drawing for adding to their applications. These APIs can also be used to create applications with fewer DX style frameworks.
XAML developers can use WinRT to pull down to the compositing layer using C # To perform custom work on the compositing layer, you do not need to drop down to the graphic layer and use DirectX and C ++ for any custom UI work. This technology can be used to use the synthesis API to animation existing elements, or to add a UI by creating a "Visual Island" of Windows. UI. Composition content in the XAML element tree.
Let's take a look at the introduction provided by Microsoft in the cloud. Let's take a look at the code.
In CompositionAPI, an animation is called an expression animation. The general effect is to change the attributes of a Visual or PropertySet with the changes of another attribute, or the attributes of another Visual or PropertySet.
There is a basic idea for a simple scenario without a limit:
Let's create a simple page first.
<Page x: Class = "TestSwipeBack. ScrollTest" xmlns =" http://schemas.microsoft.com/winfx/2006/xaml /Presentation "xmlns: x =" http://schemas.microsoft.com/winfx/2006/xaml "Xmlns: local =" using: TestSwipeBack "xmlns: d =" http://schemas.microsoft.com/expression/blend/2008 "Xmlns: mc =" http://schemas.openxmlformats.org/markup-compatibility/2006 "Mc: Ignorable =" d "Loaded =" Page_Loaded "> <Grid Background =" {ThemeResource ApplicationPageBackgroundThemeBrush} "> <ListView x: name = "_ listview" ItemsSource = "{x: Bind ItemSource, Mode = OneWay}"> <ListView. header> <Grid x: Name = "_ header"> <Grid. rowDefinitions> <RowDefinition Height = "100"/> <RowDefinition Height = "50"/> </Grid. rowDefinitions> <Grid Background = "LightBlue"> <Button> 123 </Button> <TextBlock FontSize = "25" HorizontalAlignment = "Center" verticalignment = "Center"> I will be hidden </TextBlock> </Grid> <Grid Background = "Pink" Grid. row = "1"> <Button> 123 </Button> <TextBlock FontSize = "25" HorizontalAlignment = "Center" VerticalAlignment = "Center"> I will suck the top </TextBlock> </ grid> </ListView. header> <ListView. itemTemplate> <DataTemplate> <TextBlock Text = "{Binding}"/> </DataTemplate> </ListView. itemTemplate> </ListView> </Grid> </Page>
Originally, the Header in ListViewBase is under ItemsPanelRoot. Use Canvans. SetZIndex to set ItemsPanelRoot to the bottom.
Canvas.SetZIndex(_listview.ItemsPanelRoot, -1);
Then obtain the ScrollViewer in the ListView in the background.
var _scrollviewer = FindFirstChild<ScrollViewer>(_listview);static T FindFirstChild<T>(FrameworkElement element) where T : FrameworkElement{int childrenCount = VisualTreeHelper.GetChildrenCount(element); var children = new FrameworkElement[childrenCount];
for (int i = 0; i < childrenCount; i++) { var child = VisualTreeHelper.GetChild(element, i) as FrameworkElement; children[i] = child; if (child is T) return (T)child;
} for (int i = 0; i < childrenCount; i++) if (children[i] != null) { var subChild = FindFirstChild<T>(children[i]); if (subChild != null) return subChild; } return null;
}
Obtain the ManipulationPropertySet of Visual and ScrollViewer of ListViewHeader.
var _headerVisual = ElementCompositionPreview.GetElementVisual(_header);var _manipulationPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(_scrollviewer);
Create an Expression Animation and run it.
Var _ compositor = Window. Current. Compositor; var _ headerAnimation = _ compositor. CreateExpressionAnimation ("_ manipulationPropertySet. Translation. Y>-100f? 0:-100f-_ manipulationPropertySet. translation. Y "); // _ manipulationPropertySet. translation. Y is the ScrollViewer's scroll value. When the finger moves up, that is, when the visible part moves down, translate. Y is a negative number. _ HeaderAnimation. SetReferenceParameter ("_ manipulationPropertySet", _ manipulationPropertySet); _ headerVisual. StartAnimation ("Offset. Y", _ headerAnimation );
Now, slide the Demo to see if the Header stops after rolling 100 pixels?
Note: After a Visual or propertySet is appended with an animation (StartAnimation or StartAnimationGroup), it is retrieved (propertySet. tryGetScalar) the corresponding attribute can only get 0, but the value assignment or insert value will take effect.