• Xamarin.Forms之Effects的使用


    在 Xamarin.Forms 2.1.0-pre1 ,Xamarin.Forms新增了新的Effects API. Effects是一系列方法,为了给View的渲染器添加运行时改变. 

    然而,我想强调的是, Effects天生被设计为高可复用的. 如果一个Effect能够解决一个难题, 它可能能够在你的整个APP中使用.如果你写了一个Effect来解决你的一个难题, 你能够分享它给其他遇到同样问题的人. 这篇文章尝试展示一种方式,能够帮助我们使分享Effects这件事变得很简单.

    public class ShadowEffect : PlatformEffect
    {
    	protected override void OnAttached ()
    	{
    		UpdateSize ();
    		UpdateColor ();
    		UpdateOpacity ();
    	}
    
    	protected override void OnDetached ()
    	{
    		Container.Layer.ShadowOpacity = 0;
    	}
    
    	protected override void OnElementPropertyChanged (PropertyChangedEventArgs e)
    	{
    		Debug.WriteLine (e.PropertyName);
    		if (e.PropertyName == ViewExtensions.HasShadowProperty.PropertyName) {
    			UpdateOpacity ();
    		} else if (e.PropertyName == ViewExtensions.ShadowColorProperty.PropertyName) {
    			UpdateColor ();
    		} else if (e.PropertyName == ViewExtensions.ShadowSizeProperty.PropertyName) {
    			UpdateSize ();
    		}
    	}
    
    	private void UpdateOpacity ()
    	{
    		Container.Layer.ShadowOpacity = ViewExtensions.GetHasShadow (Element) ? 1 : 0;
    	}
    
    	private void UpdateColor ()
    	{
    		var color = ViewExtensions.GetShadowColor (Element);
    		Container.Layer.ShadowColor = color.ToCGColor ();
    	}
    
    	private void UpdateSize ()
    	{
    		Container.Layer.ShadowRadius = (nfloat)ViewExtensions.GetShadowSize (Element);
    	}
    }
    

      上面的代码实在是太多了,我们可以使用下面的方式:

    public class ShadowEffect : PlatformEffect
    {
    	protected override void OnAttached ()
    	{
    		Container.Layer.ShadowOpacity = 1;
    		Container.Layer.ShadowColor = UIColor.Black.ToCGColor;
    		Container.Layer.ShadowRadius = 6;
    	}
    
    	protected override void OnDetached ()
    	{
    		Container.Layer.ShadowOpacity = 0;
    	}
    }
    

      

    使用这种方式来写Effects非常简单,但是同时也导致我们无法方便的配置它和重用它.这种方式更像前面学习的 CustomRenderer .

    ShadowEffect继承自PlatformEffect,位于特定平台的项目中. 即将custom renderers,PlatformEffects的实现是位于特定平台的项目中,然而Effect API是完全跨平台的,只不过在特定平台中使用不同的参数实现了 PlatformEffect<T, T> .一个主要的不同点就是, Effects 不包含它附加的Container/Control/Element的类型信息,这是因为它们能够被附加到任何的要素(Element).当Effect附加到一个不支持的要素(Element)时,会gracefully degrade或者抛出异常.

    如果库中包含Effect,有两个重要的属性需要设置:

    • [assembly: ResolutionGroupName ("你的公司名称")] : 用于为你的Effects设置一个公司名称来防止与其它同名的Effects发生冲突.你可以在多个程序集中设置同一公司名称.
    • [assembly: ExportEffect (typeof (ShadowEffect), "ShadowEffect")] : 用于给你的Effect设置唯一ID,通过上面的公司名称和该唯一ID来定位Effect.

    简单用法:

    给你的View添加一个Effect非常简单:

    var button = new Button { Text = "I have a shadow" };
    button.Effects.Add (Effect.Resolve ("YourCompany.ShadowEffect"));
    

      

    如果你没有为特定平台实现一个Effect. Effect.Resolve方法会返回一个非NULL值, 该值不会产生任何影响.这种设置对于只想某一平台而不是全部平台添加Effect非常的有用, 但是会有极小的内存损耗代价.

    public static class ViewEffects
    {
    	public static readonly BindableProperty HasShadowProperty =
    		BindableProperty.CreateAttached ("HasShadow", typeof (bool), typeof (ViewEffects), false, propertyChanged: OnHasShadowChanged);
    
    	private static void OnHasShadowChanged (BindableObject bindable, object oldValue, object newValue)
    	{
    		var view = bindable as View;
    		if (view == null)
    			return;
    
    		var hasShadow = (bool)newValue;
    		if (hasShadow) {
    			view.Effects.Add (new ShadowEffect ());
    		} else {
    			var toRemove = view.Effects.FirstOrDefault (e => e is ShadowEffect);
    			if (toRemove != null)
    				view.Effects.Remove (toRemove);
    		}
    	}
    
    	public static readonly BindableProperty ShadowSizeProperty =
    		BindableProperty.CreateAttached ("ShadowSize", typeof (double), typeof (ViewEffects), 0d);
    
    	public static readonly BindableProperty ShadowColorProperty =
    		BindableProperty.CreateAttached ("ShadowColor", typeof (Color), typeof (ViewEffects), Color.Default);
    
    	public static void SetHasShadow (BindableObject view, bool hasShadow)
    	{
    		view.SetValue (HasShadowProperty, hasShadow);
    	}
    
    	public static bool GetHasShadow (BindableObject view)
    	{
    		return (bool)view.GetValue (HasShadowProperty);
    	}
    
    	public static void SetShadowSize (BindableObject view, double size)
    	{
    		view.SetValue (ShadowSizeProperty, size);
    	}
    
    	public static double GetShadowSize (BindableObject view)
    	{
    		return (double)view.GetValue (ShadowSizeProperty);
    	}
    
    	public static void SetShadowColor (BindableObject view, Color color)
    	{
    		view.SetValue (ShadowColorProperty, color);
    	}
    
    	public static Color GetShadowColor (BindableObject view)
    	{
    		return (Color)view.GetValue (ShadowColorProperty);
    	}
    
    	class ShadowEffect : RoutingEffect
    	{
    		public ShadowEffect () : base ("Xamarin.ShadowEffect")
    		{
    			
    		}
    	}
    }
    

      上面看上去有很多的代码,实际上只有三个附加属性(attached BindablePropertys)和几个静态的getter和 setter.唯一有点复杂的代码是OnHasShadowChanged,它里面根据附加属性的值来简单的添加或者移除Effect. 最后,代码中使用了RoutingEffect而不是直接调用Effect.Resolve方法,只是为了使分离过程更加简单,因为该方法并没有获取特定平台的类型信息的编译时间.

    Effect的使用方法:

    <Button local:ViewEffects.HasShadow="True" 
            local:ViewEffects.ShadowColor="#222222" 
            local:ViewEffects.ShadowSize="4" />
    

    或者更好的方式,在Style中使用Effect,这样你可以将Effect应用到任何/全部的Button上:

    <Style TargetType="Button">
      <Style.Setters>
        <Setter Property="local:ViewExtensions.HasShadow" Value="True" />
        <Setter Property="local:ViewExtensions.ShadowColor" Value="#232343" />
        <Setter Property="local:ViewExtensions.ShadowSize" Value="5" />
      </Style.Setters>
    </Style>
    

      

    原文地址:http://xfcomplete.net/general/2016/01/20/using-effects/

    个人理解(16/2/1):由于Forms中官方的控件的属性非常的少,很多时候,我们需要用到更多的属性,在Effects出现之前,我们只能使用CustomRenderer来在特定平台中重写某一个控件的渲染类(ViewRenderer),譬如如果想给控件View_A添加属性Pro_A,就要继承View_A来写一个子类,另外在特定平台中写Renderer,使用的时候还需要在xaml中引用<vewis:ExtendView_A

    如果使用Effect,我们可以直接写两个Effect,在官方控件<View_A   的基础上添加Effect就可以实现,而且该Effect完全是可以通用的,只要该View支持该属性,该Effect完全可以使用在不同的View中去,更别谈有Style这种工具可以全局或者局部设置样式了

  • 相关阅读:
    【万丈高楼平地起 第一季 链表是怎样链成的】
    【笔记——ASP.NET基础知识(一)】
    【万丈高楼平地起 第二季 队列和栈】
    【没有银弹No Silver Bullet】
    【简单示例:数据库表转XML】
    【软件工程小知识】
    【总结——SQL Server中的数据类型】
    【总结—.Net Framework集合类】
    【笔记——ASP.NET基础知识(二)】
    【总结——ASP.NET对象】
  • 原文地址:https://www.cnblogs.com/yz1311/p/5176446.html
Copyright © 2020-2023  润新知