Objective-C UIImage 凹角(又名自定义进度条)
Objective-C UIImage Concave Corner (aka Custom Progress Bar)
我需要帮助以编程方式在 Objective-c 中创建此图像。凹半径是图像高度的一半。
我的目标是有一个进度条,其中左侧是图像,中间是包含视图背景颜色,右侧是可拉伸图像。
编辑
@Rob 的解决方案是可行的方法。但是,我一定是实施不正确。
我创建了头文件和实现文件,并将 class 添加到现有的 UIView、progressBarView。 CustomProgress 视图出现在 IB 中,一切看起来都很棒...
...但是当我尝试使用...设置进度值时...
self.progressBarView.progress = 0.75;
...我收到 Property 'progress' not found on object of type 'UIView *'
语义警告。
而不是创建任何图像,我可能只是将 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;
}];
...I get a Property 'progress' not found on object of type 'UIView *' semantic warning
您的 IBOutlet
似乎被定义为 UIView
而不是 CustomProgressView
。
我需要帮助以编程方式在 Objective-c 中创建此图像。凹半径是图像高度的一半。
我的目标是有一个进度条,其中左侧是图像,中间是包含视图背景颜色,右侧是可拉伸图像。
编辑
@Rob 的解决方案是可行的方法。但是,我一定是实施不正确。
我创建了头文件和实现文件,并将 class 添加到现有的 UIView、progressBarView。 CustomProgress 视图出现在 IB 中,一切看起来都很棒...
...但是当我尝试使用...设置进度值时...
self.progressBarView.progress = 0.75;
...我收到 Property 'progress' not found on object of type 'UIView *'
语义警告。
而不是创建任何图像,我可能只是将 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;
}];
...I get a Property 'progress' not found on object of type 'UIView *' semantic warning
您的 IBOutlet
似乎被定义为 UIView
而不是 CustomProgressView
。