先上效果图

首先安装Behavior SDK:在Nuget中搜索安装 Microsoft.Xaml.Behaviors.Uwp.Managed 。

然后新建类,AnimationFlipViewBehavior.cs,并继承DependencyObject和IBehavior接口:

namespace TestBehavior
{
public class AnimationFlipViewBehavior: DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; set; }
public void Attach(DependencyObject associatedObject)
{
AssociatedObject = associatedObject;
}
public void Detach()
{ }
}
}

Attach是添加Behavior时被调用的方法,Detach是移除Behavior时被调用的方法。

这时在Attach中判断是否是FlipView,并且保存下来。然后按照老样子获取ScrollViewer,如果FlipView已经加载好了,就可以直接获取到ScrollViewer,否则要在FlipView的Loaded事件中获取。

 FlipView flipView;
ScrollViewer scrollViewer;
Compositor compositor;
CompositionPropertySet scrollPropSet; public DependencyObject AssociatedObject { get; private set; } public void Attach(DependencyObject associatedObject)
{
AssociatedObject = associatedObject;
if (associatedObject is FlipView flip) flipView = flip;
else throw new ArgumentException("对象不是FlipView");
scrollViewer = Helper.FindVisualChild<ScrollViewer>(flipView, "ScrollingHost");
if (scrollViewer == null)
{
flipView.Loaded += FlipView_Loaded;
}
else InitCompositionResources(scrollViewer);
} private void FlipView_Loaded(object sender, RoutedEventArgs e)
{
flipView.Loaded -= FlipView_Loaded;
var scroll = Helper.FindVisualChild<ScrollViewer>(flipView, "ScrollingHost");
if (scroll == null) throw new ArgumentNullException("ScrollViewer为空");
else scrollViewer = scroll; InitCompositionResources(scrollViewer);
} void InitCompositionResources(ScrollViewer scroll)
{
if (compositor == null) compositor = ElementCompositionPreview.GetElementVisual(flipView).Compositor;
if (scroll == null) return; scrollPropSet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer);
}
 public static class Helper
{
public static T FindVisualChild<T>(DependencyObject obj, int Index = ) where T : DependencyObject
{
if (Index == -) return null;
int count = VisualTreeHelper.GetChildrenCount(obj);
int findedcount = ;
for (int i = ; i < count; i++)
{
DependencyObject child = Windows.UI.Xaml.Media.VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
{
if (findedcount == Index)
return (T)child;
else
{
findedcount++;
}
}
else
{
T childOfChild = FindVisualChild<T>(child, findedcount);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
public static T FindVisualChild<T>(DependencyObject obj, string name) where T : DependencyObject
{
int count = VisualTreeHelper.GetChildrenCount(obj);
int findedcount = ;
for (int i = ; i < count; i++)
{
DependencyObject child = Windows.UI.Xaml.Media.VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
{
if ((child as FrameworkElement).Name == name)
return (T)child;
else
{
findedcount++;
}
}
else
{
T childOfChild = FindVisualChild<T>(child, findedcount);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
}

然后创建两个表达式动画,分别作用在中心点和缩放上。

ExpressionAnimation CenterPointAnimation;
ExpressionAnimation ScaleAnimation; void InitCompositionResources(ScrollViewer scroll)
{
if (compositor == null) compositor = ElementCompositionPreview.GetElementVisual(flipView).Compositor;
if (scroll == null) return; scrollPropSet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer);
if (CenterPointAnimation == null)
{
CenterPointAnimation = compositor.CreateExpressionAnimation("Vector3(visual.Size.X/2,visual.Size.Y/2,0)");
}
if (ScaleAnimation == null)
{
ScaleAnimation = compositor.CreateExpressionAnimation("Clamp(1- (visual.Offset.X + scroll.Translation.X) / visual.Size.X * 0.4, 0f, 1f)");
ScaleAnimation.SetReferenceParameter("scroll", scrollPropSet);
}
}

这里着重说一下ScaleAnimation。

表达式中的Clamp(value,min,max)是内置函数,当value在min和max之间的时候返回value,小于min则返回min,大于max则返回max。

FlipView中是一个ScrollViewer,横向滚动,ScrollViewer内的元素的Visual.Offset.X控制Visual的位置,而不是默认为0。所以只要判断visual.Offset.X和scroll.Translation.X的关系,就能做出动画来。

然后写一个方法,给所有Items的容器附加上这些动画。

因为默认的Items并不是Observable的,有两种解决方案,一是设置ItemsSource为一个ObservableCollection,然后注册CollectionChanged事件。这样做会让控件和页面后台代码耦合度提升。为了更干净的代码结构,这里用一个性能低一些的方法,注册FlipView的SelectionChanged事件,在这里调用InitAnimation方法。

如果每次只给SelectedItem和左右的Item附加动画,PC上测试很完美,但是手机上,或者说触摸操作的时候,会出现动画未加载的问题。这里涉及到一个FlipView和Pivot的大坑。

在键鼠操作和代码操作SelectedIndex切换页面的时候,是先触发SelectionChanged事件,再播放动画的。但是触摸操作的时候,只有当你滑屏再送手后,系统才知道到底应不应该切换页面。所以我们每次送手播放完动画和触发SelectionChanged并不同步,动画自然就不会附加到后面的Item上,所以每次我们都给所有的Item附加动画,虽然损失了部分性能,但是可以保证不出问题。

 void InitAnimation()
{
if (compositor != null)
{
for (int i = ; i < flipView.Items.Count; i++)
{
var item = flipView.ContainerFromIndex(i);
if (item is UIElement ele)
{
var visual = ElementCompositionPreview.GetElementVisual(ele);
CenterPointAnimation.SetReferenceParameter("visual", visual);
visual.StartAnimation("CenterPoint", CenterPointAnimation);
visual.StopAnimation("Scale.X");
visual.StopAnimation("Scale.Y");
ScaleAnimation.SetReferenceParameter("visual", visual);
visual.StartAnimation("Scale.X", ScaleAnimation);
visual.StartAnimation("Scale.Y", ScaleAnimation);
}
}
}
}

最后在Loaded的最后也调用一次InitAnimation,大功告成。

源代码下载

UWP:使用Behavior实现FlipView简单缩放效果的更多相关文章

  1. Android 四种简单的动画(淡入淡出、旋转、移动、缩放效果)

    最近在Android开发当中,用到的动画效果. public void onClick(View arg0) { // TODO 自动生成的方法存根 switch (arg0.getId()) { c ...

  2. [UWP]使用Picker实现一个简单的ColorPicker弹窗

    在上一篇博文<[UWP]使用Popup构建UWP Picker>中我们简单讲述了一下使用Popup构建适用于MVVM框架下的弹窗层组件Picker的过程.但是没有应用实例的话可能体现不出P ...

  3. 《JavaScript 实战》:JavaScript 实现拖拽缩放效果

    拖拉缩放效果,实现通过鼠标拖动来调整层的面积(宽高)大小,例如选框效果.这里的拖拉缩放比一般的选框复杂一点,能设置八个方位(方向)的固定触发点,能设置最小范围,最大范围和比例缩放. 跟拖放效果一样,程 ...

  4. web前端学习(三)css学习笔记部分(5)-- CSS动画--页面特效、HTML与CSS3简单页面效果实例

    CSS动画--页面特效部分内容目前仅仅观看了解内容,记录简单笔记,之后工作了进行内容的补充 7.  CSS动画--页面特效 7.1  2D.3D转换 7.1.1  通过CSS3转换,我们能够对元素进行 ...

  5. Query 一些简单的效果

    Query 一些简单的效果 $(selector).hide(speed,callback); 隐藏 $(selector).show(speed,callback); 显示 $(selector). ...

  6. 原生JS封装简单动画效果

    原生JS封装简单动画效果 一致使用各种插件,有时候对原生JS陌生了起来,所以决定封装一个简单动画效果,熟悉JS原生代码 function animate(obj, target,num){ if(ob ...

  7. iOS开发——实用技术OC篇&简单抽屉效果的实现

    简单抽屉效果的实现 就目前大部分App来说基本上都有关于抽屉效果的实现,比如QQ/微信等.所以,今天我们就来简单的实现一下.当然如果你想你的效果更好或者是封装成一个到哪里都能用的工具类,那就还需要下一 ...

  8. HTML与CSS简单页面效果实例

    本篇博客实现一个HTML与CSS简单页面效果实例 index.html <!DOCTYPE html> <html> <head> <meta charset ...

  9. iOS简单动画效果:闪烁、移动、旋转、路径、组合

    #define kDegreesToRadian(x) (M_PI * (x) / 180.0) #define kRadianToDegrees(radian) (radian*180.0)/(M_ ...

随机推荐

  1. python2和python3中的类

    经典类与新式类 例如: A B C D 四个类 D 包含 BC :   B和C分别包含A py2 在经典类中是按深度优先来继承 例如: D中查找B,B没有从A中查找 新式类中是按广度优先来查找继承的 ...

  2. EventUtil.addHandler方法

    EventUtil.addHandler: addHandler 方法,职责是分别视情况而定来使用DOM0级方法.DOM2级方法或IE方法来添加事件.   这个方法属于一个名字叫EventUtil的对 ...

  3. ReactNative开发工具有这一篇足矣

    ReactNative系列文章: 1.<逻辑性最强的React Native环境搭建与调试> 2.<ReactNative开发工具有这一篇足矣> 正文 React Native ...

  4. (转载)Bonding技术指南

    原文链接:http://www.wushiqin.com/?post=68 一.什么是网卡绑定及简单原理 网卡绑定也称作"网卡捆绑",就是使用多块物理网卡虚拟成为一块网卡,以提供负 ...

  5. 使用C#创建简单的WCF服务

    一.开发环境 操作系统:Windows 10 开发环境:VS2015 编程语言:C# IIS版本:10.0.0.0 二.添加WCF服务.Internet Information Services(II ...

  6. java系统高并发解决方案(转载收藏)

    一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构.性能的要求都很简单,随着互联网业务的不断丰富,网站 ...

  7. Tkinter开发第一个桌面程序HelloWorld

    在Python3中是tkinter,Python2中是Tkinter Tkinter是Python 官方承认的标准 GUI 方案(de-facto standard),因为是Python自带安装,决定 ...

  8. SpringMVC原理及非注解配置详解

    1. Spring介绍 Spring MVC是Spring提供的一个强大而灵活的web框架.借助于注解,Spring MVC提供了几乎是POJO的开发模式,使得控制器的开发和测试更加简单. 这些控制器 ...

  9. 关于使用JQuery追加Option标签时使用三元运算符添加选中属性的解决办法

    $(data.resultList).each(function () {                        var selectedFlag = ${sessionScope.userI ...

  10. MS MDS系列之MDS层次结构(Hierarchy)

    在Master Data Services中,Hierarchy的作用主要用于: 对同属性成员进行分组 聚合成员用于分析和报告输出 写在开始:显示层次结构(Explicit Hierarchy)即将在 ...