【问题标题】:Objective-C UIImage Concave Corner (aka Custom Progress Bar)Objective-C UIImage 凹角(又名自定义进度条)
【发布时间】:2019-07-21 21:01:43
【问题描述】:

我需要在 Objective-c 中以编程方式创建此图像的帮助。凹面半径是图像高度的一半。

我的目标是有一个进度条,其中左侧是图像,中间是包含视图背景颜色,右侧是可拉伸图像。


编辑

@Rob 的解决方案是可行的方法。但是,我一定是执行不正确。

我创建了头文件和实现文件并将类添加到现有的 UIView、progressBarView。 CustomProgress 视图显示在 IB 中,一切看起来都很棒...

...但是当我尝试设置进度值时...

self.progressBarView.progress = 0.75;

...我收到 Property 'progress' not found on object of type 'UIView *' 语义警告。

【问题讨论】:

  • 我假设这是一个编译时警告?如果是这样,我怀疑尽管您设置了进度视图的基类,但您的IBOutlet 似乎被定义为UIView 而不是CustomProgress/CustomProgressView
  • 这确实是问题所在。谢谢!

标签: ios objective-c uiimage


【解决方案1】:

我可能只是将cornerRadius 应用于主进度视图以及显示进度的视图,而不是创建任何图像。所以,想象一下下面的视图层次结构:

主要的进度视图是后面的白色边框视图。它有一个子视图,progressSubview(上面以蓝色突出显示),它显示了迄今为止的进展(并且会随着我们更新 progress 属性而改变)。而绿色和蓝色视图只是固定大小的progressSubview 的子视图,显示为progressSubview,它剪切了它的子视图,改变了大小。

应用圆角半径非常容易。通过避免任何图像或自定义drawRect,我们可以根据需要对progressSubview 进行动画更改:

例如

//  CustomProgressView.h

@import UIKit;

NS_ASSUME_NONNULL_BEGIN

IB_DESIGNABLE
@interface CustomProgressView : UIView

@property (nonatomic) CGFloat progress;

@end

NS_ASSUME_NONNULL_END

//  CustomProgressView.m

#import "CustomProgressView.h"

@interface CustomProgressView ()

@property (nonatomic, weak) UIView *progressSubview;
@property (nonatomic, weak) UIView *greenView;
@property (nonatomic, weak) UIView *redView;

@end

@implementation CustomProgressView

- (instancetype)init {
    return [self initWithFrame:CGRectZero];
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if ((self = [super initWithCoder:aDecoder])) {
        [self configure];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:frame])) {
        [self configure];
    }
    return self;
}

- (void)configure {
    UIView *subview = [[UIView alloc] init];
    subview.backgroundColor = [UIColor clearColor];
    subview.clipsToBounds = true;
    self.layer.borderColor = [[UIColor whiteColor] CGColor];
    self.layer.borderWidth = 1;

    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    self.redView = redView;

    UIView *greenView = [[UIView alloc] init];
    greenView.backgroundColor = [UIColor greenColor];
    self.greenView = greenView;

    [self addSubview:subview];
    [subview addSubview:redView];
    [subview addSubview:greenView];

    self.progressSubview = subview;
}

- (void)layoutSubviews {
    [super layoutSubviews];

    self.layer.cornerRadius = MIN(self.bounds.size.height, self.bounds.size.width) / (CGFloat)2.0;
    self.progressSubview.layer.cornerRadius = MIN(self.bounds.size.height, self.bounds.size.width) / (CGFloat)2.0;
    [self updateProgressSubview];

    self.redView.frame = self.bounds;

    CGRect rect = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.origin.x + self.bounds.size.width / 2.0, self.bounds.origin.y + self.bounds.size.height);
    self.greenView.frame = rect;
}

- (void)setProgress:(CGFloat)progress {
    _progress = progress;
    [self updateProgressSubview];
}

- (void)updateProgressSubview {
    CGRect rect = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.origin.x + self.bounds.size.width * self.progress, self.bounds.origin.y + self.bounds.size.height);
    self.progressSubview.frame = rect;
}

- (void)prepareForInterfaceBuilder {
    [super prepareForInterfaceBuilder];

    self.progress = 0.75;
}

@end

然后你可以像这样更新进度:

[UIView animateWithDuration:0.25 animations:^{
    self.progressView.progress = 0.75;
}];

...我在“UIView *”语义警告类型的对象上找不到属性“进度”

您的IBOutlet 似乎被定义为UIView 而不是CustomProgressView

【讨论】:

  • 混“self”有什么原因。和“_”?
  • setProgress中,使用_progress很关键(因为在setProgress中使用self.progress = ...最终会再次调用setProgress,导致无限循环)。但在其他地方,使用self.progress 是谨慎的(我已经相应地更新了上面的updateProgressSubview)。
  • 所以使用“自我”。在 setProgress 之外:是一种风格选择吗?
  • 这是最佳实践,恕我直言。 99% 的时间,self.progress 只会检索_progress 的内容,所以它们是相同的。但是,如果在未来某个日期,您决定实现一个自定义 getter 来做其他/额外的事情。如果您在整个代码中使用了_progress ivar,则您必须返回并修复所有这些引用。如果您总是尽可能地使用 getter,那么您的代码就不会过时。想想我们的自定义设置器的类比。我们这样做了,然后你得到了一些更新 _progress 的代码,我们的自定义设置器将是徒劳的。与吸气剂相同。
  • Use Accessor Methods to Get or Set Property Values。事实上,当他们谈到您可以使用合成的 ivars 时,他们说,“对象使用访问器方法或点语法访问自己的属性是最佳实践……”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-29
  • 1970-01-01
  • 2017-02-04
  • 2010-10-29
相关资源
最近更新 更多