【问题标题】:Drawing Circles In Xamarin.iOS (Xamarin Monotouch) for Showing Progress Graphically在 Xamarin.iOS (Xamarin Monotouch) 中绘制圆圈以图形方式显示进度
【发布时间】:2015-07-29 07:03:43
【问题描述】:

因为我对 Xamarin World 和它的控件非常陌生。我想在我的单点触控应用程序中添加圈子以显示工作进度。为了显示进度,我必须在圆圈中标记一个弧。如果可能的话,任何人都可以帮助我提供示例代码。等待答复,非常感谢。

【问题讨论】:

  • 我看到您对 iOS 非常熟悉。您对它的 Xamarin 方面有疑问吗?基本上,您可以在 Xamarin.iOS 中执行与在 Objective-C-iOS 中相同的操作(即创建 UIView、加载一些 UIImage、添加 UILabel、旋转图像等)。
  • @FelixAlcala 感谢您的回复。我得到了解决方案。(用户界面组件)由 Xamarin 制作
  • 啊,有趣。组件的名称是什么?

标签: c# ios xamarin xamarin.ios


【解决方案1】:

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 值需要参考当前视图而不是父父视图。

【讨论】:

    【解决方案2】:

    在 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. 将百分比画成中间的字符串

    要绘制字符串,您需要将字符串转换为 NSAttributedString,然后使用 CTLine 绘制文本,如下所示:

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

    【讨论】:

    • 感谢您的时间和精力。但我已经使用来自 xamarin 的名为“Radial Progress”的组件实现了它。再次感谢
    • @Cheesbaron 你知道如何改变“径向进度”视图的背景颜色吗?
    • 顺便说一下,在@Cheesebaron 的例子中,你应该使用 FillEllipseInRect 而不是 AddEllipseInRect... 并添加 BackgroundColor = UIColor.Clear;在你 UIView 派生的构造函数中......我已经被困了一个小时......;)
    【解决方案3】:

    @SARATH 提供的答案因复制和粘贴而略有改动,但并未产生预期的结果。

    将 _degrees 更改为 _percentComplete

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

    为绘制一个完整的圆添加了常量浮点值(FULL_CIRCLE)

    将 _percentComplete 乘以 FULL_CIRCLE 以获得两条弧的结束角度(具有不同方向)

    半径的计算

      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%

    【讨论】:

    • 如何让它互动?意味着我想制作一个录像机按钮,其中绿色部分将与视频同时填充。
    • 对不起,我没有找到动画图表的方法
    • @mjwheat 它对我有用,但我想从顶部开始,而不是从右侧开始。我尝试将 CGContext 旋转到 270/-90 度。但它总是从右侧开始。我也尝试将 startangle 更改为 270,但它也没有影响。你能帮忙吗?
    • @Monica 当您说您尝试更改起始角度时,您指的是这一行吗path.AddArc(x, y, _radius, 0, _percentComplete * FULL_CIRCLE, true); g.AddPath(path); 0 是起始角度,下一个 arg 是结束角度。您是否尝试过修改这两个值?
    • 是的,我也尝试改变方向..但它不影响。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-01
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多