在Xamarin.iOS(Xamarin Monotouch)中绘制圆圈以图形方式显示进度

时间:2015-07-29 07:03:43

标签: c# ios xamarin xamarin.ios

因为我对 Xamarin 世界非常陌生并且对其控件不熟悉。我想在我的单声道触摸应用程序中添加Circles to Show Work Progress。为了显示进度,我必须在圆圈中标记一个圆弧。如果可能,任何人都可以帮我一个示例代码。等待回答,非常感谢。i like to add image like this with two text filed init

3 个答案:

答案 0 :(得分:12)

Result of the view

using System;
    using UIKit;
    using CoreGraphics;

    namespace CircleTest.Touch
    {
        public class CircleGraph : UIView
        {
            int _radius = 10;
            int _lineWidth = 10;
            nfloat _degrees = 0.0f;
            UIColor _backColor = UIColor.FromRGB(46, 60, 76);
            UIColor _frontColor = UIColor.FromRGB(234, 105, 92);
            //FromRGB (234, 105, 92);

        public CircleGraph (CGRect frame, int lineWidth, nfloat degrees)
        {
            _lineWidth = lineWidth; 
            _degrees = degrees; 
            this.Frame = new CGRect(frame.X, frame.Y, frame.Width, frame.Height);
            this.BackgroundColor = UIColor.Clear; 

        }

        public CircleGraph (CGRect frame, int lineWidth, UIColor backColor, UIColor frontColor)
        {
            _lineWidth = lineWidth;
            this.Frame = new CGRect(frame.X, frame.Y, frame.Width, frame.Height);
            this.BackgroundColor = UIColor.Clear;

        }

        public override void Draw (CoreGraphics.CGRect rect)
        {
            base.Draw (rect);

            using (CGContext g = UIGraphics.GetCurrentContext ()) {
                _radius = (int)( (this.Bounds.Width) / 3) - 8;
                DrawGraph(g, this.Bounds.GetMidX(), this.Bounds.GetMidY());
            };
        }

        public void DrawGraph(CGContext g,nfloat x0,nfloat y0) {
            g.SetLineWidth (_lineWidth);

            // Draw background circle
            CGPath path = new CGPath ();
            _backColor.SetStroke ();
            path.AddArc (x0, y0, _radius, 0, 2.0f * (float)Math.PI, true);
            g.AddPath (path);
            g.DrawPath (CGPathDrawingMode.Stroke);

            // Draw overlay circle
            var pathStatus = new CGPath ();
            _frontColor.SetStroke ();
            pathStatus.AddArc(x0, y0, _radius, 0, _degrees * (float)Math.PI, false);
            g.AddPath (pathStatus);
            g.DrawPath (CGPathDrawingMode.Stroke);
        }
    }
}

实际上这就是我实际应该做的事情。它为我工作

这就是它的样子。你可以像创建类文件一样创建它,只需你可以分配给UIView。 有关更多参考,您可以使用此示例项目Pi Graph

[编辑]: Draw方法最初将View.Frame x,y传递给DrawGraph方法。这应该是View.Bounds(上面修改过以反映这一点)。请记住,框架x,y是对包含的超级视图的引用,并且边界是引用当前视图的。如果视图是在0,0处添加的话,这可能会有效,但是一旦你开始在UI中移动它就会消失。绘制弧时,传递给AddArc的x,y的值需要引用当前视图而不是父超级视图。

答案 1 :(得分:10)

在GLContext上画一个圆圈并不难做到,与在Objective-C或Swift中做的一样。

我假设您要创建自己可以重复使用的视图。为此,只需继承UIView

即可
public class CircleView : UIView
{
}

现在,要在新的自定义视图中绘制任何内容,您要覆盖Draw方法:

public override void Draw(RectangleF rect)
{
    base.Draw(rect);
    // draw stuff in here
}

要绘制内容,您需要从UIGraphics获取当前上下文,这可以这样做:

using (var gctx = UIGraphics.GetCurrentContext())
{
    // use gctx to draw stuff
}

您获得的CGContext与Android上的Canvas非常相似。它有辅助方法来绘制弧形,圆形,矩形,点等等。

因此,要在该上下文中绘制一个简单的圆圈,您可以:

gctx.SetFillColor(UIColor.Cyan.CGColor);
gctx.AddEllipseInRect(rect);

所以你要把所有的东西结合起来:

public class CircleView : UIView
{
    public override Draw(RectangleF rect)
    {
        base.Draw(rect);
        using (var gctx = UIGraphics.GetCurrentContext())
        {
            gctx.SetFillColor(UIColor.Cyan.CGColor);
            gctx.AddEllipseInRect(rect);
        }
    }
}

就是这样!嗯,不完全是,这是您需要开始考虑如何绘制进度指示器的地方。我认为可能有用的是:

  1. 画背景
  2. 绘制边框
  3. 根据百分比进度计算度数
  4. 使用度数使用gctx.AddArc()创建弧线,可以采用角度并绘制弧线。
  5. 在中间绘制百分比作为字符串
  6. 要绘制字符串,您需要将字符串转换为NSAttributedString,然后使用CTLine绘制文字,如:

    using(var line = new CTLine(nsAttrString))
        line.Draw(gctx);
    

答案 2 :(得分:1)

@SARATH提供的答案的轻微改动,因为复制和粘贴没有产生预期的结果。

将_degrees更改为_percentComplete

通过为percentComplete添加参数并为_backColor和_frontColor添加缺少的成员变量赋值来修改颜色的修复重载构造函数

添加常量浮点值以绘制整圆(FULL_CIRCLE)

通过FULL_CIRCLE乘以_percentComplete来获取两个弧的结束角度(具有不同的方向)

计算半径

  public class CircleGraph : UIView
  {
      const float FULL_CIRCLE = 2 * (float)Math.PI;
      int _radius = 10;
      int _lineWidth = 10;
      nfloat _percentComplete = 0.0f;
      UIColor _backColor = UIColor.LightGray; //UIColor.FromRGB(46, 60, 76);
      UIColor _frontColor = UIColor.Green; //UIColor.FromRGB(234, 105, 92);

      public CircleGraph(CGRect frame, int lineWidth, nfloat percentComplete)
      {
         _lineWidth = lineWidth;
         _percentComplete = percentComplete;
         this.Frame = new CGRect(frame.X, frame.Y, frame.Width, frame.Height);
         this.BackgroundColor = UIColor.Clear;

      }

      public CircleGraph(CGRect frame, int lineWidth, nfloat percentComplete, UIColor backColor, UIColor frontColor)
      {
         _lineWidth = lineWidth;
         _percentComplete = percentComplete;
         this.Frame = new CGRect(frame.X, frame.Y, frame.Width, frame.Height);
         this.BackgroundColor = UIColor.Clear;
         _backColor = backColor;
         _frontColor = frontColor;
      }

      public override void Draw(CoreGraphics.CGRect rect)
      {
         base.Draw(rect);

         using (CGContext g = UIGraphics.GetCurrentContext())
         {
            var diameter = Math.Min(this.Bounds.Width, this.Bounds.Height);
            _radius = (int)(diameter / 2) - _lineWidth;

            DrawGraph(g, this.Bounds.GetMidX(), this.Bounds.GetMidY());
         };
      }

      public void DrawGraph(CGContext g, nfloat x, nfloat y)
      {
         g.SetLineWidth(_lineWidth);

         // Draw background circle
         CGPath path = new CGPath();
         _backColor.SetStroke();
         path.AddArc(x, y, _radius, 0, _percentComplete * FULL_CIRCLE, true);
         g.AddPath(path);
         g.DrawPath(CGPathDrawingMode.Stroke);

         // Draw overlay circle
         var pathStatus = new CGPath();
         _frontColor.SetStroke();

         // 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);
      }
   }

示例

var circleGraph = new CircleGraph(circleGraphView.Frame, 20, 0.75f);

CircleGraph 75%

CircleGraph displaying 75%