0
我真的很沮喪,因爲我試圖在iOS上用CoreAnimation自上週以來動畫一個餅圖(具有透明洞的弧段)。CALayer自定義屬性動畫與Xamarin
此刻,我用一個CAShapeLayer和它的Path-Property繪製ArcSegment。它看起來不錯,但我無法爲此屬性製作動畫。 我想用CABasicAnimation來動畫像Radius,Segments等Layer屬性。
有沒有人在這裏,誰能告訴我如何解決這個問題? 謝謝。
問候 羅尼
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");
}
}
這並不爲工作'Xamarin.iOS'爲不支持'@ dynamic'屬性:https://bugzilla.xamarin.com/show_bug.cgi?id = 38823 – SushiHangover