当前位置: 移动技术网 > IT编程>开发语言>.net > WPF中自定义GridLengthAnimation

WPF中自定义GridLengthAnimation

2017年12月08日  | 移动技术网IT编程  | 我要评论

需求

我们想在编辑一个列表中某一个条目时,将编辑的详情内容也放置当前面,比如右侧。

可以通过将一个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"/>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网