如何在 iOS 中制作如下图所示的仪表视图?

Posted

技术标签:

【中文标题】如何在 iOS 中制作如下图所示的仪表视图?【英文标题】:how to make a gauge view as in the following image in iOS? 【发布时间】:2019-03-26 12:29:38 【问题描述】:

我查看了像 gaugekit 这样的库,但它们并没有解决我的问题。 是否有任何其他库可以制作图像中的仪表视图? 如果没有,那我该如何解决呢?

正如@DonMag 指出的那样。 我试图通过在仪表视图顶部添加一个视图来对仪表套件进行更改....但结果并不好。

所以我在实际仪表之间留出空间。

https://imgur.com/Qk1EpcV

【问题讨论】:

欢迎来到 ***。请使用tour 并查看How to Ask。你说“gaugekit 不能解决我的问题”?您需要描述您是如何尝试使用它的,什么对您不起作用,以及您在尝试修改它以满足您的需求时遇到了麻烦。 听起来像是 CoreGraphicsUIBezierPath 的工作。但是,如果您不熟悉这些内容,您可能想要按照 Ben 在他的回答中提出的建议进行操作。 @EmilioPelaez 我熟悉 CoreGraphics 和 UIBezierPath 但我卡住的地方是在仪表之间留出空间,所以如果可能的话,如果我去的话,你能告诉我如何制作视图CoreGraphics 和 UIBezierPath 【参考方案1】:

我建议您创建自己的自定义视图,这并不难。这是我将如何做到的。为了清楚起见,我省略了一些细节,但您可以在 cmets 中看到我为此建议的解决方案。

首先,创建UIVew 的子类。我们将需要一个属性来跟踪仪表位置。这将进入您的 .h 文件。

@interface GaugeView : UIView

@property (nonatomic) CGFloat knobPosition;

@end

接下来,添加实现。 GaugeView 本身就是一个视图,因此它将用作我们想要的其他部分的容器。我已经使用awakeFromNib 函数进行初始化,以便您可以在 Storyboard 中使用该类作为 UIView。如果您愿意,也可以从 init 函数进行初始化。

我没有提供中心旋钮的代码,但我建议您只需创建一个带有白色圆盘(或两个用于制作灰色圆圈)的视图和用于保存文本部分的标签,然后在其下方使用灰色指针添加图像视图。可以通过对其应用旋转变换来移动指针。

- (void)awakeFromNib 
    [super awakeFromNib];

    // Initialization part could also be placed in init
    [self createSegmentLayers];

    // Add knob views to self
    // :

    // Start somewhere
    self.knobPosition = 0.7;

接下来,创建细分。这里没有添加实际的形状,因为它们需要视图的大小。最好推迟到layoutSubviews

- (void)createSegmentLayers 
    for (NSInteger segment = 0; segment < 10; ++segment) 
        // Create the shape layer and set fixed properties
        CAShapeLayer *shapeLayer = [CAShapeLayer layer];

        // Color can be set differently for each segment
        shapeLayer.strokeColor = [UIColor blueColor].CGColor;
        shapeLayer.lineWidth = 1.0;

        [self.layer addSublayer:shapeLayer];
    

接下来,我们需要响应视图的大小变化。这也是我们创建实际形状的地方。

- (void)layoutSubviews 
    [super layoutSubviews];

    // Dynamically create the segment paths and scale them to the current view width
    NSInteger segment = 0;
    for (CAShapeLayer *layer in self.layer.sublayers) 
        layer.frame = self.layer.bounds;
        layer.path = [self createSegmentPath:segment radius:self.bounds.size.width / 2.0].CGPath;

        // If we should fill or not depends on the knob position
        // Since the knobPosition's range is 0.0..1.0 we can just multiply by 10
        // and compare to the segment number
        layer.fillColor = segment < (_knobPosition * 10) ? layer.strokeColor : nil;

        // Assume we added the segment layers first
        if (++segment >= 10)
            break;
    

    // Move and size knob images
    // :

然后我们需要形状。

- (UIBezierPath *)createSegmentPath:(NSInteger)segment radius:(CGFloat)radius 
    UIBezierPath *path = [UIBezierPath bezierPath];

    // We could also use a table with start and end angles for different segment sizes
    CGFloat startAngle = segment * 21.0 + 180.0 - 12.0;
    CGFloat endAngle = startAngle + 15.0;

    // Draw the path, two arcs and two implicit lines
    [path addArcWithCenter:CGPointMake(radius, radius) radius:0.9 * radius startAngle:DEG2RAD(startAngle) endAngle:DEG2RAD(endAngle) clockwise:YES];
    [path addArcWithCenter:CGPointMake(radius, radius) radius:0.75 * radius startAngle:DEG2RAD(endAngle) endAngle:DEG2RAD(startAngle) clockwise:NO];
    [path closePath];

    return path;

最后,我们要响应knobPosition 属性的更改。调用setNeedsLayout 将触发对layoutSubviews 的调用。

// Position is 0.0 .. 1.0
- (void)setKnobPosition:(CGFloat)knobPosition 
    // Rotate the knob image to point at the right segment
    // self.knobPointerImageView.transform = CGAffineTransformMakeRotation(DEG2RAD(knobPosition * 207.0 + 180.0));

    _knobPosition = knobPosition;
    [self setNeedsLayout];

这就是它现在的样子。添加旋钮、一些颜色和可能不同大小的段,你就完成了!

【讨论】:

【参考方案2】:

根据我看到的图像,最简单的解决方案可能是创建 12 个图像,然后随着图像所代表的值的增长或缩小,以编程方式交换这些图像。

【讨论】:

据我所知,如果我按照你的方式进行,我不是必须为每个百分比管理图像 这是该解决方案的缺点,是的。但是我在链接中看到的仪表会产生 11 张图像。可以使用UILabelUIImage 上绘制实际数字。

以上是关于如何在 iOS 中制作如下图所示的仪表视图?的主要内容,如果未能解决你的问题,请参考以下文章

如何创建一个视图或布局,如一年中所有月份的 CalendarView?

如何在 Swift 3 中制作下拉菜单

NSLayoutContraints:如何将底部视图放置在两个标签中较高者的下方?

表视图控制器上的 ios 栏按钮项

如何在android中制作这样的动画?

js如何制作图片轮播