I'm trying to implement the collapsible page header. The main idea is I have to change the height of page header (min height 60 and max is 160) depending on the changes in the scrollviewer
.
Here is the result I want to achieve.
Initial state of the page header
Page header when scrolled down
My XAML code:
<controls:CollapsablePageHeader>
<controls:CollapsablePageHeader>
<Grid x:Name="CollapsablePageHeaderGrid" MinHeight="150" Background="{StaticResource ApplicationAccentBackgroundColorBrush}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock Text="25 905" HorizontalAlignment="Center" FontSize="50" Foreground="{StaticResource ApplicationAlternativeAccentColorBrush}"/>
<controls:TengeSignControl FontSize="50" Foreground="{StaticResource ApplicationAlternativeAccentColorBrush}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Image Source="/Assets/CreditCard.png" Height="20" Width="20" Margin="0,5,5,0"/>
<TextBlock Text="Bank of Arkham City" FontSize="{StaticResource BigTextSize}" Foreground="{StaticResource ApplicationAlternativeAccentColorBrush}"/>
</StackPanel>
</StackPanel>
</Grid>
</controls:CollapsablePageHeader>
</controls:CollapsablePageHeader>
<ScrollViewer x:Name="MainScrollViewer" Grid.Row="1" IsTabStop="False" ScrollViewer.HorizontalScrollMode="Disabled" ScrollViewer.VerticalScrollBarVisibility="Hidden">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!--Layout for user favorite payment templates-->
<toolkitControls:DropShadowPanel Style="{StaticResource DefaultCardDropShadowEffect}">
<Grid Style="{StaticResource CardConontrolElement}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Uid="Favorites" Style="{StaticResource SectionHeaderTextBlock}" HorizontalAlignment="Left" />
<GridView x:Name="UserTemplatesSelector" Grid.Row="1" ItemsSource="{Binding PaymentTemplates}" ItemTemplate="{StaticResource UserTemplatesDataTemplate}" Margin="-10,0,-10,0" Padding="10,0,0,0" Style="{StaticResource DefaultHorizontalGridView}" ItemContainerStyle="{StaticResource DefaultHorizontalGridViewItemContainer}">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</Grid>
</toolkitControls:DropShadowPanel>
<!-- Layout for last operations -->
<toolkitControls:DropShadowPanel Grid.Row="1" Margin="0,20,0,0" Style="{StaticResource DefaultCardDropShadowEffect}">
<Grid Style="{StaticResource CardConontrolElement}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Uid="LastOperations" Style="{StaticResource SectionHeaderTextBlock}"/>
<ListView x:Name="LastOperationsListView" Grid.Row="1" ItemsSource="{Binding LastTransactions}" ItemTemplate="{StaticResource LastOperationsDataTemplate}" Margin="0,10,0,0" ItemContainerStyle="{StaticResource DefaultListViewItemContainer}"/>
<Button x:Name="ShowMoreOperationsButton" Content="Показать всё" Grid.Row="2" Style="{StaticResource TiltableAccentButton}"/>
</Grid>
</toolkitControls:DropShadowPanel>
<!-- Layour for bound cards -->
<toolkitControls:DropShadowPanel Grid.Row="2" Margin="0,20" Style="{StaticResource DefaultCardDropShadowEffect}">
<Grid Style="{StaticResource CardConontrolElement}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Uid="LastOperations" Style="{StaticResource SectionHeaderTextBlock}" Typography.Capitals="AllSmallCaps"/>
<ListView x:Name="BoundCardListView" Grid.Row="1" ItemsSource="{Binding BoundCards}" ItemTemplate="{StaticResource BoundCardsDataTemplate}" Margin="0,10,0,0" ItemContainerStyle="{StaticResource DefaultListViewItemContainer}"/>
<Button x:Name="ShowMoreCardsButton" Content="Показать всё" Grid.Row="2" Style="{StaticResource TiltableAccentButton}"/>
</Grid>
</toolkitControls:DropShadowPanel>
</Grid>
</ScrollViewer>`
I have tried to implement this using the Compositor.CreateExpressionAnimation
but it did not work well. Could anyone please tell me how to do this?
UPDATE:
Throws an exception when try to animate the Scale.X or Scale.Y value, but I cannot figure out why. Other Visual items work excellent with Scale animation.
ExpressionNode headerTranslationAnimation = EF.Conditional(progressNode < 1, 0, -scrollingProperties.Translation.Y - clampSizeNode);
headerVisual.StartAnimation("Offset.Y", headerTranslationAnimation);
ExpressionNode headerScaleAnimation = EF.Lerp(1, 1.25f, EF.Clamp(scrollingProperties.Translation.Y / 50, 0, 1));
headerVisual.StartAnimation("Scale.X", headerScaleAnimation);
headerVisual.StartAnimation("Scale.Y", headerScaleAnimation);
Exception at headerVisual.StartAnimation
:
System.ArgumentException: 'The parameter is incorrect.The animation failed to connect.'
Updated xaml:
<Grid x:Name="LayoutRoot" Style="{StaticResource DefaultLayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollViewer x:Name="MainScrollViewer" IsTabStop="False" ScrollViewer.HorizontalScrollMode="Disabled" ScrollViewer.VerticalScrollBarVisibility="Hidden">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid x:Name="CollapsiblePageHeader" Height="150" VerticalAlignment="Top">
<ScrollViewer>
<Grid>
<Rectangle Height="300" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle.Fill>
<ImageBrush ImageSource="ms-appx:///Assets/Samples/SampleParallaxImage.jpg"/>
</Rectangle.Fill>
</Rectangle>
<StackPanel>
<StackPanel x:Name="TitleContainer" VerticalAlignment="Top" HorizontalAlignment="Center" Orientation="Horizontal">
<TextBlock x:Name="TitleText" Text="25 905" FontSize="50" Foreground="{StaticResource ApplicationAlternativeAccentColorBrush}"/>
<controls:TengeSignControl x:Name="TitleImage" FontSize="50" Foreground="{StaticResource ApplicationAlternativeAccentColorBrush}"/>
</StackPanel>
<StackPanel x:Name="SubtitleContainer" HorizontalAlignment="Center" VerticalAlignment="Top" Grid.Row="1" Orientation="Horizontal">
<Image x:Name="SubtitleImage" Source="/Assets/CreditCard.png" Height="20" Width="20" Margin="0,5,5,0"/>
<TextBlock x:Name="SubtitleText" Text="Bank of Arkham City" FontSize="{StaticResource BigTextSize}" Foreground="{StaticResource ApplicationAlternativeAccentColorBrush}"/>
</StackPanel>
</StackPanel>
</Grid>
</ScrollViewer>
</Grid>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!--Layout for user favorite payment templates-->
<toolkitControls:DropShadowPanel Grid.Row="1" Style="{StaticResource DefaultCardDropShadowEffect}">
<Grid Style="{StaticResource CardConontrolElement}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Uid="Favorites" Style="{StaticResource SectionHeaderTextBlock}" HorizontalAlignment="Left" />
<GridView x:Name="UserTemplatesSelector" Grid.Row="1" ItemsSource="{Binding PaymentTemplates}" ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.VerticalScrollMode="Disabled" ItemTemplate="{StaticResource UserTemplatesDataTemplate}" Margin="-10,0,-10,0" Padding="10,0,0,0" Style="{StaticResource DefaultGridView}" ItemContainerStyle="{StaticResource DefaultGridViewItemContainer}"/>
</Grid>
</toolkitControls:DropShadowPanel>
<!-- Layout for last operations -->
<toolkitControls:DropShadowPanel Grid.Row="2" Margin="0,20,0,0" Style="{StaticResource DefaultCardDropShadowEffect}">
<Grid Style="{StaticResource CardConontrolElement}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Uid="LastOperations" Style="{StaticResource SectionHeaderTextBlock}"/>
<ListView x:Name="LastOperationsListView" Grid.Row="1" ScrollViewer.VerticalScrollMode="Disabled" ItemsSource="{Binding LastTransactions}" ItemTemplate="{StaticResource LastOperationsDataTemplate}" Margin="0,10,0,0" ItemContainerStyle="{StaticResource DefaultListViewItemContainer}"/>
<Button x:Name="ShowMoreOperationsButton" Content="Показать всё" Grid.Row="2" Style="{StaticResource TiltableAccentButton}"/>
</Grid>
</toolkitControls:DropShadowPanel>
<!-- Layour for bound cards -->
<toolkitControls:DropShadowPanel Grid.Row="3" Margin="0,20" Style="{StaticResource DefaultCardDropShadowEffect}">
<Grid Style="{StaticResource CardConontrolElement}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="Привязанные карты" Style="{StaticResource SectionHeaderTextBlock}" Typography.Capitals="AllSmallCaps"/>
<ListView x:Name="BoundCardListView" Grid.Row="1" ScrollViewer.VerticalScrollMode="Disabled" ItemsSource="{Binding BoundCards}" ItemTemplate="{StaticResource BoundCardsDataTemplate}" Margin="0,10,0,0" ItemContainerStyle="{StaticResource DefaultListViewItemContainer}"/>
<Button x:Name="ShowMoreCardsButton" Content="Показать всё" Grid.Row="2" Style="{StaticResource TiltableAccentButton}"/>
</Grid>
</toolkitControls:DropShadowPanel>
</Grid>
</Grid>
</ScrollViewer>
<CommandBar x:Name="PaymentOperations" Grid.Row="1">
<AppBarButton x:Name="VendorPayment" Label="Оплата поставщиков" Icon="Shop" Click="MerchantPayment_Click"/>
<AppBarButton x:Name="p2pPayment" Label="P2P оплата" Icon="Remote" Click="PersonToPersonPayment_Click"/>
<AppBarButton x:Name="w2wPayment" Label="Перевод с кошелька на кошелек" Icon="Manage" Click="WalletToWalletPayment_Click"/>
</CommandBar>
</Grid>
Full xaml.cs:
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
// Get the PropertySet that contains the scroll values from MyScrollViewer
_scrollerPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(MainScrollViewer);
_compositor = _scrollerPropertySet.Compositor;
// Create a PropertySet that has values to be referenced in the ExpressionAnimations below
_props = _compositor.CreatePropertySet();
_props.InsertScalar("progress", 0);
_props.InsertScalar("clampSize", 150);
_props.InsertScalar("scaleFactor", 0.7f);
// Get references to our property sets for use with ExpressionNodes
var scrollingProperties = _scrollerPropertySet.GetSpecializedReference<ManipulationPropertySetReferenceNode>();
var props = _props.GetReference();
var progressNode = props.GetScalarProperty("progress");
var clampSizeNode = props.GetScalarProperty("clampSize");
var scaleFactorNode = props.GetScalarProperty("scaleFactor");
// Create and start an ExpressionAnimation to track scroll progress over the desired distance
ExpressionNode progressAnimation = EF.Clamp(-scrollingProperties.Translation.Y / clampSizeNode, 0, 1);
_props.StartAnimation("progress", progressAnimation);
// Get the backing visual for the header so that its properties can be animated
Visual headerVisual = ElementCompositionPreview.GetElementVisual(CollapsiblePageHeader);
// Create and start an ExpressionAnimation to clamp the header's offset to keep it onscreen
ExpressionNode headerTranslationAnimation = EF.Conditional(progressNode < 1, 0, -scrollingProperties.Translation.Y - clampSizeNode);
// Works fine
headerVisual.StartAnimation("Offset.Y", headerTranslationAnimation);
ExpressionNode headerScaleAnimation = EF.Lerp(1, 1.25f, EF.Clamp(scrollingProperties.Translation.Y / 50, 0, 1));
// Exception here
headerVisual.StartAnimation("Scale.X", headerScaleAnimation);
headerVisual.StartAnimation("Scale.Y", headerScaleAnimation);
//Set the header's CenterPoint to ensure the overpan scale looks as desired
headerVisual.CenterPoint = new Vector3((float)(CollapsiblePageHeader.ActualWidth / 2), (float)CollapsiblePageHeader.ActualHeight, 0);
// Create and start an ExpressionAnimation to scale the profile image with scroll position
ExpressionNode scaleAnimation = EF.Lerp(1, scaleFactorNode, progressNode);
// Get backing visuals for the text blocks so that their properties can be animated
Visual titleVisual = ElementCompositionPreview.GetElementVisual(TitleText);
Visual titleImageVisual = ElementCompositionPreview.GetElementVisual(TitleImage);
Visual subtitleVisual = ElementCompositionPreview.GetElementVisual(SubtitleText);
Visual subtitleImageVisual = ElementCompositionPreview.GetElementVisual(SubtitleImage);
// Create an ExpressionAnimation that moves between 1 and 0 with scroll progress, to be used for text block opacity
ExpressionNode textOpacityAnimation = EF.Clamp(1 - (progressNode * 2), 0, 1);
// Start opacity and scale animations on the text block visuals
titleVisual.StartAnimation("Scale.X", scaleAnimation);
titleVisual.StartAnimation("Scale.Y", scaleAnimation);
titleImageVisual.StartAnimation("Scale.X", scaleAnimation);
titleImageVisual.StartAnimation("Scale.Y", scaleAnimation);
subtitleVisual.StartAnimation("Opacity", textOpacityAnimation);
subtitleVisual.StartAnimation("Scale.X", scaleAnimation);
subtitleVisual.StartAnimation("Scale.Y", scaleAnimation);
subtitleImageVisual.StartAnimation("Opacity", textOpacityAnimation);
subtitleImageVisual.StartAnimation("Scale.X", scaleAnimation);
subtitleImageVisual.StartAnimation("Scale.Y", scaleAnimation);
// Get the backing visuals for the text and button containers so that their properites can be animated
Visual subtitleContainerVisual = ElementCompositionPreview.GetElementVisual(SubtitleContainer);
// When the header stops scrolling it is 150 pixels offscreen. We want the text header to end up with 50 pixels of its content
// offscreen which means it needs to go from offset 0 to 100 as we traverse through the scrollable region
ExpressionNode contentOffsetAnimation = progressNode * 100;
subtitleContainerVisual.StartAnimation("Offset.Y", contentOffsetAnimation);
}
This can be easily done without the community toolkit if your minimum target version is Anniversary Update. Considering you do, let's take you through the solution.
page
and copy paste the code from codeBehind and make necessary changes in your UI and code behind refering to the Desinger and Code Behind in the "Shrinking Header" Page of the downloaded repo. Please Note: you can see an active App on the store for the same repo on the store at the Link: Windows Dev Labs UI App