Ios 使用Xamarin的CALayer自定义特性动画

Ios 使用Xamarin的CALayer自定义特性动画,ios,xamarin,cashapelayer,Ios,Xamarin,Cashapelayer,我真的很沮丧,因为从上周开始,我一直在尝试用CoreAnimation在iOS上制作饼图(带有透明孔的圆弧段)的动画 目前,我正在使用带有路径属性的CAShapeLayer绘制ArcSegment。它看起来很棒,但我无法设置此属性的动画。 我想用CABasicAnimation设置层属性(如半径、分段等)的动画 有人能告诉我怎么解决这个问题吗? 多谢各位 问候 罗尼 公共类ArcSegmentLayer:CAShapeLayer{ 私有常量字符串StartAngleProperty=“Start

我真的很沮丧,因为从上周开始,我一直在尝试用CoreAnimation在iOS上制作饼图(带有透明孔的圆弧段)的动画

目前,我正在使用带有路径属性的CAShapeLayer绘制ArcSegment。它看起来很棒,但我无法设置此属性的动画。 我想用CABasicAnimation设置层属性(如半径、分段等)的动画

有人能告诉我怎么解决这个问题吗? 多谢各位

问候 罗尼

公共类ArcSegmentLayer:CAShapeLayer{
私有常量字符串StartAngleProperty=“StartAngle”;
私有常量字符串EndAngleProperty=“EndAngle”;
公共静态无效注册表属性(){
RegisterDynamicProperty(typeof(arcegmentlayer)、StartAngleProperty、typeof(float));
RegisterDynamicProperty(typeof(ArcSegmentLayer)、EndAngleProperty、typeof(float));
}
公共ArcSegmentLayer(){}
[导出(“initWithLayer:”)]
公共ArcSegmentLayer(ArcSegmentLayer层){
this.LineWidth=layer.LineWidth;
this.Frame=layer.Frame;
this.FillColor=layer.FillColor;
this.StrokeColor=layer.StrokeColor;
this.Segments=layer.Segments;
this.Margin=layer.Margin;
}
#区域属性
公共浮球{
获取{return ObjCProperties.GetFloatProperty(Handle,StartAngleProperty);}
设置{
SetFloatProperty(句柄、StartAngleProperty、值);
}
}
公共浮动端角{
get{return ObjCProperties.GetFloatProperty(句柄,EndAngleProperty);}
设置{
SetFloatProperty(句柄、EndAngleProperty、值);
}
}
公共九段{
获取{返回段;}
设置{
如果(段!=值){
段=值;
此.SetNeedsDisplay();
}
}
}
公共贷款保证金{
得到{
收益率;
}
设置{
如果(边距!=值){
保证金=价值;
此.SetNeedsDisplay();
}
}
}
#端区
[导出(“需要显示forkey:”)]
公共静态布尔需要显示forkey(NSString键){
return key==StartAngleProperty
||key==EndAngleProperty
||键==“边距”
||键==“段”
||键==“线宽”
||键==“StrokeColor”
||CALayer.NeedsDisplayForKey(键);
}
[导出(“显示”)]
公共覆盖无效显示(){
base.Display();
Console.WriteLine(此.EndAngle);
this.Path=CreateSegments().CGPath;
}
[导出(“actionForKey:”)]
公共覆盖NSObject ActionForKey(字符串eventKey){
/*
如果(eventKey==EndAngleProperty){
CABasicAnimation动画=CABasicAnimation.FromKeyPath(eventKey);
animation.TimingFunction=CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear);
animation.From=new NSNumber(this.EndAngle);//PresentationLayer.ValueForKey(new NSString(eventKey));
//animation.Duration=cattransition.1;
动画。持续时间=0;
返回动画;
}else if(eventKey==StartAngleProperty){
CABasicAnimation动画=CABasicAnimation.FromKeyPath(eventKey);
animation.TimingFunction=CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear);
animation.From=新的NSNumber(this.StartAngle);
动画。持续时间=0;
返回动画;
}*/
返回base.ActionForKey(eventKey);
}
私有UIBezierPath CreateSegments(){
var path=新的UIBezierPath();
nfloat片段大小=(nfloat)(360.0/(nfloat)this.Segments);
nfloat STARTSENGLE=0;
nfloat endSegAngle=起始节段+节段尺寸;
如果(this.Segments>1){
var fromSeg=(nint)((双)this.Segments)*this.StartAngle)/360.0;
var-toSeg=(nint)(((双)此.段)*此.端角)/360.0);
对于(var seg=0;seg=fromSeg&&seg    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");
    }
}