WPF中自定义GridLengthAnimation
程序员文章站
2023-11-17 09:09:40
需求
我们想在编辑一个列表中某一个条目时,将编辑的详情内容也放置当前面,比如右侧。
可以通过将一个grid,分成两个cloumn,动态调整两个cloumn的widt...
需求
我们想在编辑一个列表中某一个条目时,将编辑的详情内容也放置当前面,比如右侧。
可以通过将一个grid,分成两个cloumn,动态调整两个cloumn的width,就可以实现这个需求。
我们知道,clomun的width是个,而默认的动画没有这样子的。我们就需要自己实现这样一人动画。
设计
我们从animation的类图上看到
我们可以从需求
我们想在编辑一个列表中某一个条目时,将编辑的详情内容也放置当前面,比如右侧。
可以通过将一个grid,分成两个cloumn,动态调整两个cloumn的width,就可以实现这个需求。
我们知道,clomun的width是个gridlength,而默认的动画没有这样子的。我们就需要自己实现这样一人动画。
设计
我们从animation的类图上看到animationtimeline继承,重写其getcurrentvalue
public class gridlengthanimation : animationtimeline { /// <summary> /// returns the type of object to animate /// </summary> public override type targetpropertytype => typeof(gridlength); /// <summary> /// creates an instance of the animation object /// </summary> /// <returns>returns the instance of the gridlengthanimation</returns> protected override system.windows.freezable createinstancecore() { return new gridlengthanimation(); } /// <summary> /// dependency property for the from property /// </summary> public static readonly dependencyproperty fromproperty = dependencyproperty.register("from", typeof(gridlength), typeof(gridlengthanimation)); /// <summary> /// clr wrapper for the from depenendency property /// </summary> public gridlength from { get { return (gridlength)getvalue(gridlengthanimation.fromproperty); } set { setvalue(gridlengthanimation.fromproperty, value); } } /// <summary> /// dependency property for the to property /// </summary> public static readonly dependencyproperty toproperty = dependencyproperty.register("to", typeof(gridlength), typeof(gridlengthanimation)); /// <summary> /// clr wrapper for the to property /// </summary> public gridlength to { get { return (gridlength)getvalue(gridlengthanimation.toproperty); } set { setvalue(gridlengthanimation.toproperty, value); } } /// <summary> /// animates the grid let set /// </summary> /// <param name="defaultoriginvalue">the original value to animate</param> /// <param name="defaultdestinationvalue">the final value</param> /// <param name="animationclock">the animation clock (timer)</param> /// <returns>returns the new grid length to set</returns> public override object getcurrentvalue(object defaultoriginvalue, object defaultdestinationvalue, animationclock animationclock) { double fromval = ((gridlength)getvalue(gridlengthanimation.fromproperty)).value; double toval = ((gridlength)getvalue(gridlengthanimation.toproperty)).value; if (fromval > toval) return new gridlength((1 - animationclock.currentprogress.value) * (fromval - toval) + toval, gridunittype.star); else return new gridlength(animationclock.currentprogress.value * (toval - fromval) + fromval, gridunittype.star); }
如上所示,我们仿着默认动画实现了from,to,同时将其属性定义为gridlength,当动画执行时,我们重写了getcurrentvalue,使其根据from/to属性相关联。
优化
通过以上代码,我们实现了在gridlength变化时,实现动画。但是,试用后我们发现,动画,有点太线性。这个时候,怎么办?
可以通过引入easingfunction来实现。我们知道easingfunction其实就是一个与时间t有关的时间函数f(t).通过时间函数的处理,我们使动画过渡不要那么线性。
/// <summary> /// the <see cref="easingfunction" /> dependency property's name. /// </summary> public const string easingfunctionpropertyname = "easingfunction"; /// <summary> /// gets or sets the value of the <see cref="easingfunction" /> /// property. this is a dependency property. /// </summary> public ieasingfunction easingfunction { get { return (ieasingfunction)getvalue(easingfunctionproperty); } set { setvalue(easingfunctionproperty, value); } } /// <summary> /// identifies the <see cref="easingfunction" /> dependency property. /// </summary> public static readonly dependencyproperty easingfunctionproperty = dependencyproperty.register( easingfunctionpropertyname, typeof(ieasingfunction), typeof(gridlengthanimation), new uipropertymetadata(null));
对应的,还要重写getcurrentvalue函数。
public override object getcurrentvalue(object defaultoriginvalue, object defaultdestinationvalue, animationclock animationclock) { double fromval = ((gridlength)getvalue(fromproperty)).value; double toval = ((gridlength)getvalue(toproperty)).value; //check that from was set from the caller //if (fromval == 1) // //set the from as the actual value // fromval = ((gridlength)defaultdestinationvalue).value; double progress = animationclock.currentprogress.value; ieasingfunction easingfunction = easingfunction; if (easingfunction != null) { progress = easingfunction.ease(progress); } if (fromval > toval) return new gridlength((1 - progress) * (fromval - toval) + toval, gridunittype.star); return new gridlength(progress * (toval - fromval) + fromval, gridunittype.star); }
使用
<anim:gridlengthanimation storyboard.targetproperty="width" from="0" to="*" duration="0:0:0.5"/>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: 如何利用大数据更好地促进SEO优化服务