zoukankan      html  css  js  c++  java
  • 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这种工具可以全局或者局部设置样式了

  • 相关阅读:
    BestCoder6 1002 Goffi and Squary Partition(hdu 4982) 解题报告
    codeforces 31C Schedule 解题报告
    codeforces 462C Appleman and Toastman 解题报告
    codeforces 460C. Present 解题报告
    BestCoder3 1002 BestCoder Sequence(hdu 4908) 解题报告
    BestCoder3 1001 Task schedule(hdu 4907) 解题报告
    poj 1195 Mobile phones 解题报告
    二维树状数组 探索进行中
    codeforces 460B Little Dima and Equation 解题报告
    通过Sql语句控制SQLite数据库增删改查
  • 原文地址:https://www.cnblogs.com/yz1311/p/5176446.html
Copyright © 2011-2022 走看看