UWP中使用Composition API实现吸顶(1)

简介: 原文:UWP中使用Composition API实现吸顶(1)前几天需要在UWP中实现吸顶,就在网上找了一些文章: 吸顶大法 -- UWP中的工具栏吸顶的实现方式之一 在UWP中页面滑动导航栏置顶 发现前人的实现方式大多是控制ListViewBase的Header变换高度,或者建立一个ScrollViewer在里面放置ListViewBase。
原文: UWP中使用Composition API实现吸顶(1)

前几天需要在UWP中实现吸顶,就在网上找了一些文章:

吸顶大法 -- UWP中的工具栏吸顶的实现方式之一

在UWP中页面滑动导航栏置顶

发现前人的实现方式大多是控制ListViewBase的Header变换高度,或者建立一个ScrollViewer在里面放置ListViewBase。经过测试,这两种方法或多或少的都有问题。所以我想试试用Composition API实现吸顶的效果。

首先先了解一下Composition API是什么。

Windows.UI.Composition 是可以从任何通用 Windows 平台 (UWP) 应用程序调用的声明性保留模式 API ,从而可以直接在应用程序中创建合成对象、 动画和效果。 该 API 是对诸如 XAML 等现有框架的一个强大补充,从而为 UWP 应用程序开发人员提供了一个熟悉的 C# 图面以供添加到其应用程序。 这些 API 还可以用于创建 DX 样式框架较少的应用程序。

XAML 开发人员可以使用 WinRT“下拉”到采用 C# 的合成层,以便在该合成层上执行自定义工作,而无需一直下拉到图形层并针对任何自定义 UI 工作使用 DirectX 和 C++。 此技术可用于使用合成 API 对现有元素进行动画处理,也可用于通过在 XAML 元素树内创建 Windows.UI.Composition 内容的“视觉岛”来增加 UI。

只看这几句微软给的介绍也是云里来雾里去的,还是看代码吧。

CompositionAPI中有一种动画叫表达式动画。大致效果就是让一个Visual或者PropertySet的属性随着自身另一个属性,或者另一个Visual或者PropertySet的属性的变化而变化。

对于不含Pivot的简单情况,就有这样一个基本的思路了:

  1. 获取到ListViewBase的ScrollViewer;
  2. 获取到ScrollViewer的ManipulationPropertySet和ListViewHeader的Visual;
  3. 让ManipulationPropertySet和Visual发生关系。

我们先来建立一个简单的页面。

<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" VerticalAlignment="Center">我会被隐藏</TextBlock>
                    </Grid>
                    <Grid Background="Pink" Grid.Row="1">
                        <Button>123</Button>
                        <TextBlock FontSize="25" HorizontalAlignment="Center" VerticalAlignment="Center">我会吸顶</TextBlock>
                    </Grid>
                </Grid>
            </ListView.Header>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding }" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

原本ListViewBase里Header是在ItemsPanelRoot下方的,使用Canvans.SetZIndex把ItemsPanelRoot设置到下方。

Canvas.SetZIndex(_listview.ItemsPanelRoot, -1);

然后在后台获取ListView内的ScrollViewer。

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;
}

获取ListViewHeader的Visual和ScrollViewer的ManipulationPropertySet。

var _headerVisual = ElementCompositionPreview.GetElementVisual(_header);
var _manipulationPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(_scrollviewer);

创建表达式动画,然后运行。

var _compositor = Window.Current.Compositor;
var _headerAnimation = _compositor.CreateExpressionAnimation("_manipulationPropertySet.Translation.Y > -100f ? 0: -100f -_manipulationPropertySet.Translation.Y");
//_manipulationPropertySet.Translation.Y是ScrollViewer滚动的数值,手指向上移动的时候,也就是可视部分向下移动的时候,Translation.Y是负数。

_headerAnimation.SetReferenceParameter("_manipulationPropertySet", _manipulationPropertySet);

_headerVisual.StartAnimation("Offset.Y", _headerAnimation);

 

现在滑动Demo看看,是不是在滚动100像素之后,Header就停住了?

 

注:在一个Visual或者propertySet被附加了动画(即StartAnimation或者StartAnimationGroup)之后,取出(propertySet.TryGetScalar)相应的属性就只能取到0,但是赋值或者插入数值是会生效的。

 

目录
相关文章
|
1月前
|
JavaScript 前端开发 API
Vue 3新特性详解:Composition API的威力
【10月更文挑战第25天】Vue 3 引入的 Composition API 是一组用于组织和复用组件逻辑的新 API。相比 Options API,它提供了更灵活的结构,便于逻辑复用和代码组织,特别适合复杂组件。本文将探讨 Composition API 的优势,并通过示例代码展示其基本用法,帮助开发者更好地理解和应用这一强大工具。
30 1
|
3月前
|
存储 JavaScript 前端开发
敲黑板!vue3重点!一文了解Composition API新特性:ref、toRef、toRefs
该文章深入探讨了Vue3中Composition API的关键特性,包括`ref`、`toRef`、`toRefs`的使用方法与场景,以及它们如何帮助开发者更好地管理组件状态和促进逻辑复用。
敲黑板!vue3重点!一文了解Composition API新特性:ref、toRef、toRefs
|
2月前
|
缓存 JavaScript 前端开发
深入理解 Vue 3 的 Composition API 与新特性
本文详细探讨了 Vue 3 中的 Composition API,包括 setup 函数的使用、响应式数据管理(ref、reactive、toRefs 和 toRef)、侦听器(watch 和 watchEffect)以及计算属性(computed)。我们还介绍了自定义 Hooks 的创建与使用,分析了 Vue 2 与 Vue 3 在响应式系统上的重要区别,并概述了组件生命周期钩子、Fragments、Teleport 和 Suspense 等新特性。通过这些内容,读者将能更深入地理解 Vue 3 的设计理念及其在构建现代前端应用中的优势。
39 0
深入理解 Vue 3 的 Composition API 与新特性
|
2月前
|
JavaScript API
|
2月前
|
API
《vue3第四章》Composition API 的优势,包含Options API 存在的问题、Composition API 的优势
《vue3第四章》Composition API 的优势,包含Options API 存在的问题、Composition API 的优势
27 0
|
4月前
|
前端开发 JavaScript API
Vue 3 新特性:在 Composition API 中使用 CSS Modules
Vue 3 新特性:在 Composition API 中使用 CSS Modules
|
4月前
|
JavaScript 前端开发 API
Vue.js 3.x新纪元:Composition API引领潮流,Options API何去何从?前端开发者必看的抉择指南!
【8月更文挑战第30天】Vue.js 3.x 引入了 Composition API,为开发者提供了更多灵活性和控制力。本文通过示例代码对比 Composition API 与传统 Options API 的差异,帮助理解两者在逻辑复用、代码组织、类型推断及性能优化方面的不同,并指导在不同场景下的选择。Composition API 改善了代码可读性和维护性,尤其在大型项目中优势明显,同时结合 TypeScript 提供更好的类型推断和代码提示,减少错误并提升开发效率。尽管如此,在选择 API 时仍需考虑项目复杂性、团队熟悉度等因素。
55 0
|
23天前
|
JSON API 数据格式
淘宝 / 天猫官方商品 / 订单订单 API 接口丨商品上传接口对接步骤
要对接淘宝/天猫官方商品或订单API,需先注册淘宝开放平台账号,创建应用获取App Key和App Secret。之后,详细阅读API文档,了解接口功能及权限要求,编写认证、构建请求、发送请求和处理响应的代码。最后,在沙箱环境中测试与调试,确保API调用的正确性和稳定性。
|
1月前
|
供应链 数据挖掘 API
电商API接口介绍——sku接口概述
商品SKU(Stock Keeping Unit)接口是电商API接口中的一种,专门用于获取商品的SKU信息。SKU是库存量单位,用于区分同一商品的不同规格、颜色、尺寸等属性。通过商品SKU接口,开发者可以获取商品的SKU列表、SKU属性、库存数量等详细信息。
|
1月前
|
JSON API 数据格式
店铺所有商品列表接口json数据格式示例(API接口)
当然,以下是一个示例的JSON数据格式,用于表示一个店铺所有商品列表的API接口响应