【UWP】对 Thickness 类型属性进行动画
好几个月没写 blog 了,一个是在忙新版的碧影壁纸,另一方面是等(观望)周年更新的 api(不过现在还是比较失望,仍然没法支持矩形以外的 Clip)。闲话少说,进入主题。
在 UWP 中,出于性能考虑,微软是不建议、不推荐对会影响布局的属性进行动画的。例如 Width 和 Height 这种,如果真的需要对这些属性进行动画的话(毕竟需求就摆在那里),可以将 Animation 的 EnableDependentAnimation 属性设置为 true 来对这些属性进行动画的。
但是,对于 Thickness 类型来说,这是行不通的,因为 UWP 中并没有 ThicknessAnimation 这种动画类型(PS:WPF 里是有这种动画类型的说)。
不过既然我标题都写了出来,那办法肯定是有的。Thickness 就是四个方向分量,也就是说,对这四个方向分量进行动画就等于对这个 Thickness 进行了动画。
还有另外一点要注意的是,Thickness 类型的四个属性并不是依赖属性。
例如:
- control.Margin.Left = ;
这一句是没有效果的。
要实现效果,只能对 Margin 属性从新赋一个值:
- var margin = control.Margin;
- margin.Left = ;
- control.Margin = margin;
也就是说,我们需要一个可绑定的 Margin。(我就叫它 BindableMargin)
新建一个用户控件:
为什么是用户控件?因为经过我的发现,我们自定义的类的依赖属性,得有 xaml 文件才能进行动画。(不信你可以试试^-^)
然后修改 BindableMargin.xaml 如下:
- <DependencyObject x:Class="AnimateThicknessDemo.BindableMargin"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d" />
相当简单的一段 xaml,设计器就无视好了。重点在 BindableMargin.xaml.cs 里,修改代码:
- public partial class BindableMargin
- {
- public static readonly DependencyProperty BottomProperty = DependencyProperty.Register(nameof(Bottom), typeof(double), typeof(BindableMargin), new PropertyMetadata(default(double), BottomChanged));
- public static readonly DependencyProperty LeftProperty = DependencyProperty.Register(nameof(Left), typeof(double), typeof(BindableMargin), new PropertyMetadata(default(double), LeftChanged));
- public static readonly DependencyProperty RightProperty = DependencyProperty.Register(nameof(Right), typeof(double), typeof(BindableMargin), new PropertyMetadata(default(double), RightChanged));
- public static readonly DependencyProperty TopProperty = DependencyProperty.Register(nameof(Top), typeof(double), typeof(BindableMargin), new PropertyMetadata(default(double), TopChanged));
- private readonly FrameworkElement _owner;
- public BindableMargin(FrameworkElement owner)
- {
- if (owner == null)
- {
- throw new ArgumentNullException(nameof(owner));
- }
- _owner = owner;
- }
- public double Bottom
- {
- get
- {
- var ownerBottom = _owner.Margin.Bottom;
- var bottom = (double)GetValue(BottomProperty);
- if (ownerBottom.Equals(bottom) == false)
- {
- SetValue(BottomProperty, ownerBottom);
- }
- return ownerBottom;
- }
- set
- {
- SetValue(BottomProperty, value);
- }
- }
- public double Left
- {
- get
- {
- var ownerLeft = _owner.Margin.Left;
- var left = (double)GetValue(LeftProperty);
- if (ownerLeft.Equals(left) == false)
- {
- SetValue(LeftProperty, ownerLeft);
- }
- return ownerLeft;
- }
- set
- {
- SetValue(LeftProperty, value);
- }
- }
- public double Right
- {
- get
- {
- var ownerRight = _owner.Margin.Right;
- var right = (double)GetValue(RightProperty);
- if (ownerRight.Equals(right) == false)
- {
- SetValue(RightProperty, ownerRight);
- }
- return ownerRight;
- }
- set
- {
- SetValue(RightProperty, value);
- }
- }
- public double Top
- {
- get
- {
- var ownerTop = _owner.Margin.Top;
- var top = (double)GetValue(TopProperty);
- if (ownerTop.Equals(top) == false)
- {
- SetValue(TopProperty, ownerTop);
- }
- return ownerTop;
- }
- set
- {
- SetValue(TopProperty, value);
- }
- }
- private static void BottomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var obj = (BindableMargin)d;
- var value = (double)e.NewValue;
- var owner = obj._owner;
- var margin = owner.Margin;
- margin.Bottom = value;
- owner.Margin = margin;
- }
- private static void LeftChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var obj = (BindableMargin)d;
- var value = (double)e.NewValue;
- var owner = obj._owner;
- var margin = owner.Margin;
- margin.Left = value;
- owner.Margin = margin;
- }
- private static void RightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var obj = (BindableMargin)d;
- var value = (double)e.NewValue;
- var owner = obj._owner;
- var margin = owner.Margin;
- margin.Right = value;
- owner.Margin = margin;
- }
- private static void TopChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var obj = (BindableMargin)d;
- var value = (double)e.NewValue;
- var owner = obj._owner;
- var margin = owner.Margin;
- margin.Top = value;
- owner.Margin = margin;
- }
- }
别看代码这么多,其实不复杂。构造函数传入需要动画的控件。然后四个方向的依赖属性,值发生改变时回写到控件上。
然后动画的例子代码:
- BindableMargin margin = new BindableMargin(control);
- DoubleAnimation animation = new DoubleAnimation();
- animation.EnableDependentAnimation = true;
- animation.From = ;
- animation.To = ;
- animation.Duration = TimeSpan.FromSeconds();
- Storyboard.SetTarget(animation, margin);
- Storyboard.SetTargetProperty(animation, "Left");
- await storyboard.BeginAsync();// WinRTXamlToolkit 里的扩展方法。
- margin.Left = ;
另外建议在动画播放完毕后,执行一次常规的赋值操作(一般赋最终值),因为视乎机器的配置,Storyboard 会有一定程度的跳帧,在低端的机器,可能动画就完全跳过去了。
说了这么多,还是说说有啥应用吧。
这是一个类似 IT 之家的通知控件。通过动画了 Margin 的 Right 来实现的。
Demo 下载地址:AnimateThicknessDemo.zip
当然应用还有很多,例如对 Border 的圆角进行动画。通过这么一种“桥”的方式,我们可以对很多属性,并不局限于 Thickness 类型,也进行动画,这里就留给各位看官发挥想象了。
【UWP】对 Thickness 类型属性进行动画的更多相关文章
- [UWP]使用SpringAnimation创建有趣的动画
1. 什么是自然动画 最近用弹簧动画(SpringAnimation)做了两个番茄钟,关于弹簧动画官方文档已经介绍得够详细了,这篇文章就摘录一些官方文档核心内容. 在传统UI中,关键帧动画(KeyFr ...
- 自定义 Layer 属性的动画
默认情况下,CALayer 及其子类的绝大部分标准属性都可以执行动画,无论是添加一个 CAAnimation 到 Layer(显式动画),亦或是为属性指定一个动作然后修改它(隐式动画). 但有时候 ...
- swfit 中的类型属性说明
swift 中不叫做类属性,叫类型属性,因为在swift中,struct 和enum也是可以有这种属性的,叫类属性明显不准. 有以下注意事项: 对于值类型(指结构体和枚举)可以定义存储型和计算型类型属 ...
- html <input>标签类型属性type(file、text、radio、hidden等)详细介绍
html <input>标签类型属性type(file.text.radio.hidden等)详细介绍 转载请注明:文章转载自:[169IT-最新最全的IT资讯] html <inp ...
- 1.4.2 solr字段类型--(1.4.2.1)字段类型定义和字段类型属性
1.4.2 solr字段类型 (1.4.2.1) 字段类型定义和字段类型属性. (1.4.2.2) solr附带的字段类型 (1.4.2.3) 使用货币和汇率 (1.4.2.4) 使用Dates(日期 ...
- Spring、基本类型属性和集合类型属性的注入
Spring 还可以对基本属性和集合类型属性进行注入: public interface PersonIService { public String getBaseProperty(); publi ...
- Silverlight代码编写对控件的PlaneProjection.RotationY属性控制动画
Canvas c; void btnDraw_Click(object sender, RoutedEventArgs e) { Storyboard story = new Storyboard() ...
- Swift编程语言学习11—— 枚举全局变量、局部变量与类型属性
全局变量和局部变量 计算属性和属性监视器所描写叙述的模式也能够用于全局变量和局部变量,全局变量是在函数.方法.闭包或不论什么类型之外定义的变量,局部变量是在函数.方法或闭包内部定义的变量. 前面章节提 ...
- Swift - 类型属性(类静态属性)和类方法(类静态方法)
1,结构体struct和枚举enum的静态属性,静态方法使用static关键字 1 2 3 4 5 6 7 8 9 10 struct Account { var amount : Doub ...
随机推荐
- (String) | String.valueOf()
Map m = new HashMap(); Integer i = 5; String s = null; m.put("val1", i); m.put("val2& ...
- 老王教您怎么做cass7.1 8.0 9.1所有系列的复制狗 加密狗 破解狗
cass7.1 8.0 9.1所有系列的复制狗 加密狗 破解狗本来是出于好奇看到网上有这样的东西,学了下感觉挺简单的,如果你是cass的初学者想仅仅是想学习这个软件,不想花大价格购买正版的,这个是可以 ...
- A CIRCULAR PROGRESSBAR STYLE USING AN ATTACHED VIEWMODEL
This blog post describes how to re-template the Silverlight ProgressBar control to render a circular ...
- hadoop错误之ClassNotFoundException
http://www.cnblogs.com/kaizhangzhang/p/3495438.html 在win7下运行hadoop-1.1.2 worldcount代码的时候出现下面的错误,折腾了差 ...
- 袭击Mercurial SCM(HG)
这个叫水银的源代码管理工具尽管默默无闻,但还是得到了非常多团队的使用. 为了迎合某些团队的须要,我们也要用它来管理我们的代码. 今天的任务是先袭击学习.磨刀不误砍柴工. 对工具的掌握越快.工作的效率就 ...
- 提示Can't load package:dclite70.bpl解决方法
64位系统安装Delphi7提示Can’t load package:dclite70.bpl 2015年04月05日 ⁄ 杂谈 ⁄ 共 392字 ⁄ 字号 小 中 大 ⁄ 暂无评论 ⁄ 阅读 1,7 ...
- Retrofit
Retrofit 标签(空格分隔): 第三方&开源 Retrofit是一套RESTful架构的Android(Java)客户端实现,基于注解,提供JSON to POJO(Plain Ordi ...
- MyEclipse设置编码方式
1.windows->Preferences……打开"首选项"对话框,左侧导航树,导航到general->Workspace, 右侧Text file encoding ...
- How to create an anonymous IDA PRO database (.IDB)
Source: http://www.0xebfe.net/blog/2013/01/13/how-to-create-an-anonymous-ida-pro-database-dot-idb/ P ...
- Python Base HTTP Server
import BaseHTTPServer import cgi, random, sys MESSAGES = [ "That's as maybe, it's still a frog. ...