2016-10-02 2 views
0

지난주 이후 CoreAnimation을 사용하여 iOS에서 파이 차트 (투명한 구멍이있는 아크 세그먼트)에 애니메이션을 적용하려고하기 때문에 실제로 좌절했습니다.Xamarin을 사용하는 CALayer 맞춤형 속성 애니메이션

모멘트에서 ArcSegment를 Path 속성으로 CAShapeLayer로 그립니다. 멋져 보이지만이 속성을 움직일 수는 없습니다. CABasicAnimation을 사용하여 반지름, 세그먼트 등의 레이어 속성에 애니메이션을 적용하려고합니다.

누가이 문제를 해결할 수 있는지 알려주는 사람이 있습니까? 감사합니다.

감사 로니

public class ArcSegmentLayer : CAShapeLayer { 
    private const string StartAngleProperty = "StartAngle"; 
    private const string EndAngleProperty = "EndAngle"; 

    public static void RegisterProperties() { 
     ObjCProperties.RegisterDynamicProperty(typeof(ArcSegmentLayer), StartAngleProperty, typeof(float)); 
     ObjCProperties.RegisterDynamicProperty(typeof(ArcSegmentLayer), EndAngleProperty, typeof(float)); 
    } 

    public ArcSegmentLayer() { } 

    [Export("initWithLayer:")] 
    public ArcSegmentLayer(ArcSegmentLayer layer) { 
     this.LineWidth = layer.LineWidth; 
     this.Frame = layer.Frame; 
     this.FillColor = layer.FillColor; 
     this.StrokeColor = layer.StrokeColor; 
     this.Segments = layer.Segments; 
     this.Margin = layer.Margin; 
    } 

    #region Properties 

    public float StartAngle { 
     get { return ObjCProperties.GetFloatProperty(Handle, StartAngleProperty); } 
     set { 
      ObjCProperties.SetFloatProperty(Handle, StartAngleProperty, value); 
     } 
    } 

    public float EndAngle { 
     get { return ObjCProperties.GetFloatProperty(Handle, EndAngleProperty); } 
     set { 
      ObjCProperties.SetFloatProperty(Handle, EndAngleProperty, value); 
     } 
    } 

    public nint Segments { 
     get { return segments; } 
     set { 
      if (segments != value) { 
       segments = value; 
       this.SetNeedsDisplay(); 
      } 
     } 
    } 

    public nfloat Margin { 
     get { 
      return margin; 
     } 
     set { 
      if (margin != value) { 
       margin = value; 
       this.SetNeedsDisplay(); 
      } 
     } 
    } 

    #endregion 

    [Export("needsDisplayForKey:")] 
    public static bool NeedsDisplayForKey(NSString key) { 
     return key == StartAngleProperty 
      || key == EndAngleProperty 
      || key == "Margin" 
      || key == "Segments" 
      || key == "LineWidth" 
      || key == "StrokeColor" 
      || CALayer.NeedsDisplayForKey(key); 
    } 

    [Export("display")] 
    public override void Display() { 
     base.Display(); 

     Console.WriteLine(this.EndAngle); 

     this.Path = CreateSegments().CGPath; 
    } 

    [Export("actionForKey:")] 
    public override NSObject ActionForKey(string eventKey) { 
     /* 
     if (eventKey == EndAngleProperty) { 
      CABasicAnimation animation = CABasicAnimation.FromKeyPath(eventKey); 
      animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear); 
      animation.From = new NSNumber(this.EndAngle); //PresentationLayer.ValueForKey(new NSString(eventKey)); 
                  //animation.Duration = CATransition. 1; 
      animation.Duration = 0; 
      return animation; 
     } else if (eventKey == StartAngleProperty) { 
      CABasicAnimation animation = CABasicAnimation.FromKeyPath(eventKey); 
      animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear); 
      animation.From = new NSNumber(this.StartAngle); 
      animation.Duration = 0; 
      return animation; 
     }*/ 
     return base.ActionForKey(eventKey); 
    } 

    private UIBezierPath CreateSegments() { 
     var path = new UIBezierPath(); 

     nfloat segmentSize = (nfloat)(360.0/(nfloat)this.Segments); 
     nfloat startSegAngle = 0; 
     nfloat endSegAngle = startSegAngle + segmentSize; 

     if (this.Segments > 1) { 
      var fromSeg = (nint)((((double)this.Segments) * this.StartAngle)/360.0); 
      var toSeg = (nint)((((double)this.Segments) * this.EndAngle)/360.0); 
      for (var seg = 0; seg < this.Segments; seg++) { 
       var hiddenLayer = !(seg >= fromSeg && seg < toSeg); 
       if (!hiddenLayer) { 
        path.AppendPath(
         this.CreateSegmentPath(
          startSegAngle, endSegAngle - this.Margin)); 
       } 
       startSegAngle += segmentSize; 
       endSegAngle += segmentSize; 
      } 
     } else if (this.Segments == 1) { 
      path.AppendPath(this.CreateSegmentPath(this.StartAngle, this.EndAngle)); 
     } 
     return path; 
    } 

    private UIBezierPath CreateSegmentPath(nfloat startSegAngle, nfloat endSegAngle) { 
     var center = new CGPoint(x: this.Bounds.Width/2f, y: this.Bounds.Height/2f); 
     var radius = (nfloat)Math.Max(this.Bounds.Width, this.Bounds.Height)/2f - this.LineWidth/2f; 

     var path = UIBezierPath.FromArc(
      center, 
      radius, 
      Deg2Rad(startSegAngle - 90f), 
      Deg2Rad(endSegAngle - 90f), 
      true); 

     path.MoveTo(center); 
     path.ClosePath(); 
     path.Stroke(); 

     return path; 
    } 

    private static nfloat Deg2Rad(nfloat value) { 
     return (nfloat)(floatPI/180.0 * value); 
    } 

    private static readonly nfloat floatPI = (nfloat)Math.PI; 

    private nint segments; 
    private nfloat margin; 
} 

    [DesignTimeVisible(true)] 
public partial class ArcSegmentView : UIView { 
    public ArcSegmentView(IntPtr handle) : base(handle) { 
     this.strokeColor = UIColor.Black.CGColor; 
    } 

    #region Properties 

    [Export("StartAngle"), Browsable(true)] 
    public nfloat StartAngle { 
     get { return startAngle; } 
     set { 
      if (startAngle != value) { 
       startAngle = value; 
       ((ArcSegmentLayer)this.Layer).StartAngle = (float)value; 
       this.SetNeedsDisplay(); 
      } 
     } 
    } 

    [Export("EndAngle"), Browsable(true)] 
    public nfloat EndAngle { 
     get { return endAngle; } 
     set { 
      if (endAngle != value) { 
       endAngle = value; 
       ((ArcSegmentLayer)this.Layer).EndAngle = (float)value; 
       this.SetNeedsDisplay(); 
      } 
     } 
    } 

    [Export("Segments"), Browsable(true)] 
    public nint Segments { 
     get { return segments; } 
     set { 
      if (segments != value) { 
       segments = value; 
       ((ArcSegmentLayer)this.Layer).Segments = value; 
       this.SetNeedsDisplay(); 
      } 
     } 
    } 

    [Export("Margin"), Browsable(true)] 
    public nfloat Margin { 
     get { return margin; } 
     set { 
      if (margin != value) { 
       margin = value; 
       ((ArcSegmentLayer)this.Layer).Margin = value; 
       this.SetNeedsDisplay(); 
      } 
     } 
    } 

    [Export("LineWidth"), Browsable(true)] 
    public nfloat LineWidth { 
     get { return lineWidth; } 
     set { 
      if (lineWidth != value) { 
       lineWidth = value; 
       ((ArcSegmentLayer)this.Layer).LineWidth = value; 
       this.SetNeedsDisplay(); 
      } 
     } 
    } 

    [Export("StrokeColor"), Browsable(true)] 
    public CGColor StrokeColor { 
     get { return strokeColor; } 
     set { 
      if (StrokeColor != value) { 
       strokeColor = value; 
       ((ArcSegmentLayer)this.Layer).StrokeColor = value; 
       //this.SetNeedsDisplay(); 
      } 
     } 
    } 

    #endregion 

    [Export("layerClass")] 
    static Class LayerClass() { 
     return new Class(typeof(ArcSegmentLayer)); 
    } 

    private nfloat lineWidth; 
    private nfloat margin; 
    private nint segments; 
    private nfloat startAngle; 
    private nfloat endAngle; 
    private CGColor strokeColor; 
} 

public partial class ViewController : UIViewController { 
    protected ViewController(IntPtr handle) : base(handle) { } 

    public override void ViewDidLoad() { 
     base.ViewDidLoad(); 

     arcSegment.StartAngle = 45; 
     arcSegment.EndAngle = 90; 
     arcSegment.Margin = 2; 
     arcSegment.StrokeColor = UIColor.Red.CGColor; 
     arcSegment.Segments = 70; 
     arcSegment.LineWidth = 10; 

     CABasicAnimation animation = CABasicAnimation.FromKeyPath("EndAngle"); 
     animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear); 
     animation.From = new NSNumber(45); 
     animation.To = new NSNumber(360); 
     animation.Duration = 10; 

     arcSegment.Layer.AddAnimation(animation, "EndAngle"); 
    } 
} 
+0

이 작동하지 않습니다를 'Xamarin.iOS' as '@dynamic' 속성을 지원하지 않습니다 : https://bugzilla.xamarin.com/show_bug.cgi?id=38823 – SushiHangover

답변

관련 문제