xamrin.ios 从上边缘而不是右边缘绘制圆形进度条
xamrin.ios draw circular progressbar from top edge instead of right edge
我正在开发 xamarin.forms 应用程序。为此我需要循环进度条。我几乎可以使用 CustomRenderer 在 xamarin.ios 中使用它,但它实际上并不是我想要的。
我在 xamarin.ios 渲染器中的圆形进度条有效,但从包含矩形的右边缘开始。但我希望它从顶部沿顺时针方向开始。
我尝试将起始角度更改为 -90 或 270,但它仍然从右侧开始,有时它也不起作用。我不确定它在哪种情况下不起作用,但我认为当我在代码中使用 Math.PI
常量时,Draw
永远不会调用。我提到了 link。
class NativeProgressBarRenderer : ViewRenderer
{
private bool _sizeChanged = false;
//private CG _paint;
private CGRect _ringDrawArea;
private nfloat _radius;
const float FULL_CIRCLE = 2 * (float)Math.PI;
// int _radius = 10;
float _lineWidth = 10;
nfloat _percentComplete = 0.0f;
UIColor _backColor = UIColor.LightGray; //UIColor.FromRGB(46, 60, 76);
UIColor _frontColor = UIColor.Green; //UIColor.FromRGB(234, 105, 92);
protected override void OnElementPropertyChanged(object sender,
System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == ProgressBar.ProgressProperty.PropertyName ||
e.PropertyName == PlayerProgressBar.RingThicknessProperty.PropertyName ||
e.PropertyName == PlayerProgressBar.RingBaseColorProperty.PropertyName ||
e.PropertyName == PlayerProgressBar.RingProgressColorProperty.PropertyName)
{
SetNeedsLayout();
SetNeedsDisplay();
}
if (e.PropertyName == VisualElement.WidthProperty.PropertyName ||
e.PropertyName == VisualElement.HeightProperty.PropertyName)
{
_sizeChanged = true;
SetNeedsLayout();
SetNeedsDisplay();
}
}
public override void Draw(CoreGraphics.CGRect rect)
{
base.Draw(rect);
using (CGContext g = UIGraphics.GetCurrentContext())
{
var progressRing = (PlayerProgressBar)Element;
// Get Metrics
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
// Screen density
var density = mainDisplayInfo.Density;
_lineWidth = (float)Math.Ceiling(progressRing.RingThickness * density);
var diameter = Math.Min(this.Bounds.Width, this.Bounds.Height);
_radius = (int)(diameter / 2) - _lineWidth;
_backColor = progressRing.RingBaseColor.ToUIColor();
_frontColor = progressRing.RingProgressColor.ToUIColor();
_percentComplete = (float)progressRing.Progress;
var x = Bounds.GetMidX();
var y = Bounds.GetMidY();
//DrawGraph(g, Bounds.Left, Bounds.Top); // Tried to change x,y
DrawGraph(g, Bounds.GetMidX(), this.Bounds.GetMidY());
};
}
public void DrawGraph(CGContext g, nfloat x, nfloat y)
{
//g.ScaleCTM(1, -1);
//g.TranslateCTM(0, -Bounds.Height);
//g.RotateCTM(270);
g.SetLineWidth(_lineWidth);
// Draw background circle
CGPath path = new CGPath();
_backColor.SetStroke();
path.AddArc(x, y, _radius, 270, _percentComplete * FULL_CIRCLE, true);
g.AddPath(path);
g.DrawPath(CGPathDrawingMode.Stroke);
// Draw overlay circle
var pathStatus = new CGPath();
_frontColor.SetStroke();
//CGAffineTransform cGAffineTransform = new CGAffineTransform();
//cGAffineTransform.Rotate(-90); // This also doesn't work
// Same Arc params except direction so colors don't overlap
pathStatus.AddArc(x, y, _radius, 0, _percentComplete * FULL_CIRCLE, false);
g.AddPath(pathStatus);
g.DrawPath(CGPathDrawingMode.Stroke);
//cGAffineTransform.Invert();
}
我希望 运行 从圆圈顶部开始。请帮忙!
谢谢
这是因为起始角度不是从0点开始的。这是它的默认坐标系:
所以每个角应该负0.5π。修改您的代码,如:
// Draw overlay circle
var pathStatus = new CGPath();
_frontColor.SetStroke();
pathStatus.AddArc(x, y, _radius, -0.25f * FULL_CIRCLE, (_percentComplete-0.25f) * FULL_CIRCLE, false);
g.AddPath(pathStatus);
g.DrawPath(CGPathDrawingMode.Stroke);
我正在开发 xamarin.forms 应用程序。为此我需要循环进度条。我几乎可以使用 CustomRenderer 在 xamarin.ios 中使用它,但它实际上并不是我想要的。
我在 xamarin.ios 渲染器中的圆形进度条有效,但从包含矩形的右边缘开始。但我希望它从顶部沿顺时针方向开始。
我尝试将起始角度更改为 -90 或 270,但它仍然从右侧开始,有时它也不起作用。我不确定它在哪种情况下不起作用,但我认为当我在代码中使用 Math.PI
常量时,Draw
永远不会调用。我提到了
class NativeProgressBarRenderer : ViewRenderer
{
private bool _sizeChanged = false;
//private CG _paint;
private CGRect _ringDrawArea;
private nfloat _radius;
const float FULL_CIRCLE = 2 * (float)Math.PI;
// int _radius = 10;
float _lineWidth = 10;
nfloat _percentComplete = 0.0f;
UIColor _backColor = UIColor.LightGray; //UIColor.FromRGB(46, 60, 76);
UIColor _frontColor = UIColor.Green; //UIColor.FromRGB(234, 105, 92);
protected override void OnElementPropertyChanged(object sender,
System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == ProgressBar.ProgressProperty.PropertyName ||
e.PropertyName == PlayerProgressBar.RingThicknessProperty.PropertyName ||
e.PropertyName == PlayerProgressBar.RingBaseColorProperty.PropertyName ||
e.PropertyName == PlayerProgressBar.RingProgressColorProperty.PropertyName)
{
SetNeedsLayout();
SetNeedsDisplay();
}
if (e.PropertyName == VisualElement.WidthProperty.PropertyName ||
e.PropertyName == VisualElement.HeightProperty.PropertyName)
{
_sizeChanged = true;
SetNeedsLayout();
SetNeedsDisplay();
}
}
public override void Draw(CoreGraphics.CGRect rect)
{
base.Draw(rect);
using (CGContext g = UIGraphics.GetCurrentContext())
{
var progressRing = (PlayerProgressBar)Element;
// Get Metrics
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
// Screen density
var density = mainDisplayInfo.Density;
_lineWidth = (float)Math.Ceiling(progressRing.RingThickness * density);
var diameter = Math.Min(this.Bounds.Width, this.Bounds.Height);
_radius = (int)(diameter / 2) - _lineWidth;
_backColor = progressRing.RingBaseColor.ToUIColor();
_frontColor = progressRing.RingProgressColor.ToUIColor();
_percentComplete = (float)progressRing.Progress;
var x = Bounds.GetMidX();
var y = Bounds.GetMidY();
//DrawGraph(g, Bounds.Left, Bounds.Top); // Tried to change x,y
DrawGraph(g, Bounds.GetMidX(), this.Bounds.GetMidY());
};
}
public void DrawGraph(CGContext g, nfloat x, nfloat y)
{
//g.ScaleCTM(1, -1);
//g.TranslateCTM(0, -Bounds.Height);
//g.RotateCTM(270);
g.SetLineWidth(_lineWidth);
// Draw background circle
CGPath path = new CGPath();
_backColor.SetStroke();
path.AddArc(x, y, _radius, 270, _percentComplete * FULL_CIRCLE, true);
g.AddPath(path);
g.DrawPath(CGPathDrawingMode.Stroke);
// Draw overlay circle
var pathStatus = new CGPath();
_frontColor.SetStroke();
//CGAffineTransform cGAffineTransform = new CGAffineTransform();
//cGAffineTransform.Rotate(-90); // This also doesn't work
// Same Arc params except direction so colors don't overlap
pathStatus.AddArc(x, y, _radius, 0, _percentComplete * FULL_CIRCLE, false);
g.AddPath(pathStatus);
g.DrawPath(CGPathDrawingMode.Stroke);
//cGAffineTransform.Invert();
}
我希望 运行 从圆圈顶部开始。请帮忙!
谢谢
这是因为起始角度不是从0点开始的。这是它的默认坐标系:
所以每个角应该负0.5π。修改您的代码,如:
// Draw overlay circle
var pathStatus = new CGPath();
_frontColor.SetStroke();
pathStatus.AddArc(x, y, _radius, -0.25f * FULL_CIRCLE, (_percentComplete-0.25f) * FULL_CIRCLE, false);
g.AddPath(pathStatus);
g.DrawPath(CGPathDrawingMode.Stroke);