实际上复制/提取 Apple 的 "continuous corners for iPhoneX"?
Actually duplicate / extract Apple's "continuous corners for iPhoneX"?
iPhoneX 的不寻常底角是 Apple 的新 (2017) “iPhoneX 的连续角”.
对于任何有经验的 iOS 程序员来说 近似 曲线是微不足道的,但是:
有没有人确切地知道如何实现这些,就像 Apple 所做的那样?
即使是私人电话,也知道就好了。
Apple 没有解释这一点似乎很奇怪。
请注意“近似”曲线是微不足道的:
重复,
对于任何有经验的 iOS 程序员来说 近似 曲线是微不足道的。
这里要问的问题具体是苹果是怎么做到的?
请不要再post任何向初学者展示如何绘制曲线和近似iPhone曲线的答案。
由于 @Aflah Bhari 的 评论,我写了一个实验性的 class,它构建了一个与 CALayer
的边界重叠的贝塞尔曲线路径。该层已将其私有 属性 continuousCorners
设置为 YES
。这是结果:
图层的边框是蓝色,路径的颜色是红色。
这是代码。您可以在 Interface Builder 的属性检查器中设置 radius
和 insets
。我通过将视图控制器视图的 class 设置为 ArcView
,将其半径设置为 30.0
并将插图设置为 (20.0, 20.0)
.
创建了上面的图像
代码如下:
ArcView.h
IB_DESIGNABLE
@interface ArcView : UIView
@property(nonatomic) IBInspectable CGFloat radius;
@property(nonatomic) IBInspectable CGSize insets;
@end
ArcView.m
#import "ArcView.h"
@interface CALayer(Private)
@property BOOL continuousCorners;
@end
@interface ArcView()
@property (strong) CALayer *borderLayer;
@end
@implementation ArcView
- (void)setRadius:(CGFloat)inRadius {
if(_radius != inRadius) {
_radius = inRadius;
self.borderLayer.cornerRadius = inRadius;
[self setNeedsDisplay];
}
}
- (void)setInsets:(CGSize)inInsets {
if(!CGSizeEqualToSize(_insets, inInsets)) {
_insets = inInsets;
[self setNeedsLayout];
[self setNeedsDisplay];
}
}
- (void)awakeFromNib {
[super awakeFromNib];
self.borderLayer = [CALayer new];
self.borderLayer.borderColor = [[UIColor blueColor] CGColor];
self.borderLayer.borderWidth = 0.5;
self.borderLayer.continuousCorners = YES;
self.borderLayer.cornerRadius = self.radius;
[self.layer addSublayer:self.borderLayer];
}
- (void)layoutSubviews {
[super layoutSubviews];
self.borderLayer.frame = CGRectInset(self.bounds, self.insets.width, self.insets.height);
}
- (void)drawRect:(CGRect)rect {
CGFloat theRadius = self.radius;
CGFloat theOffset = 1.2 * theRadius;
CGRect theRect = CGRectInset(self.bounds, self.insets.width, self.insets.height);
UIBezierPath *thePath = [UIBezierPath new];
CGPoint thePoint;
[thePath moveToPoint:CGPointMake(CGRectGetMinX(theRect) + theOffset, CGRectGetMinY(theRect))];
[thePath addLineToPoint:CGPointMake(CGRectGetMaxX(theRect) - theOffset, CGRectGetMinY(theRect))];
thePoint = CGPointMake(CGRectGetMaxX(theRect), CGRectGetMinY(theRect));
[thePath addQuadCurveToPoint:CGPointMake(CGRectGetMaxX(theRect), CGRectGetMinY(theRect) + theOffset) controlPoint:thePoint];
[thePath addLineToPoint:CGPointMake(CGRectGetMaxX(theRect), CGRectGetMaxY(theRect) - theOffset)];
thePoint = CGPointMake(CGRectGetMaxX(theRect), CGRectGetMaxY(theRect));
[thePath addQuadCurveToPoint:CGPointMake(CGRectGetMaxX(theRect) - theOffset, CGRectGetMaxY(theRect)) controlPoint:thePoint];
[thePath addLineToPoint:CGPointMake(CGRectGetMinX(theRect) + theOffset, CGRectGetMaxY(theRect))];
thePoint = CGPointMake(CGRectGetMinX(theRect), CGRectGetMaxY(theRect));
[thePath addQuadCurveToPoint:CGPointMake(CGRectGetMinX(theRect), CGRectGetMaxY(theRect) - theOffset) controlPoint:thePoint];
[thePath addLineToPoint:CGPointMake(CGRectGetMinX(theRect), CGRectGetMinY(theRect) + theOffset)];
thePoint = CGPointMake(CGRectGetMinX(theRect), CGRectGetMinY(theRect));
[thePath addQuadCurveToPoint:CGPointMake(CGRectGetMinX(theRect) + theOffset, CGRectGetMinY(theRect)) controlPoint:thePoint];
thePath.lineWidth = 0.5;
[[UIColor redColor] set];
[thePath stroke];
}
@end
希望这对您的问题有所帮助。我通过实验找到了 1.2
对 theOffset
的因数。如有必要,您可以修改此值。我为半径选择的值不是最佳值,当然可以改进。但由于它取决于与篮筐的确切距离,所以我没有投入太多时间。
自 iOS 13 起,有一个 API 可用于此:
https://developer.apple.com/documentation/quartzcore/calayercornercurve
见CALayerCornerCurve.continuous
iPhoneX 的不寻常底角是 Apple 的新 (2017) “iPhoneX 的连续角”.
对于任何有经验的 iOS 程序员来说 近似 曲线是微不足道的,但是:
有没有人确切地知道如何实现这些,就像 Apple 所做的那样?
即使是私人电话,也知道就好了。
Apple 没有解释这一点似乎很奇怪。
请注意“近似”曲线是微不足道的:
重复,
对于任何有经验的 iOS 程序员来说 近似 曲线是微不足道的。
这里要问的问题具体是苹果是怎么做到的?
请不要再post任何向初学者展示如何绘制曲线和近似iPhone曲线的答案。
由于 @Aflah Bhari 的 评论,我写了一个实验性的 class,它构建了一个与 CALayer
的边界重叠的贝塞尔曲线路径。该层已将其私有 属性 continuousCorners
设置为 YES
。这是结果:
图层的边框是蓝色,路径的颜色是红色。
这是代码。您可以在 Interface Builder 的属性检查器中设置 radius
和 insets
。我通过将视图控制器视图的 class 设置为 ArcView
,将其半径设置为 30.0
并将插图设置为 (20.0, 20.0)
.
代码如下:
ArcView.h
IB_DESIGNABLE
@interface ArcView : UIView
@property(nonatomic) IBInspectable CGFloat radius;
@property(nonatomic) IBInspectable CGSize insets;
@end
ArcView.m
#import "ArcView.h"
@interface CALayer(Private)
@property BOOL continuousCorners;
@end
@interface ArcView()
@property (strong) CALayer *borderLayer;
@end
@implementation ArcView
- (void)setRadius:(CGFloat)inRadius {
if(_radius != inRadius) {
_radius = inRadius;
self.borderLayer.cornerRadius = inRadius;
[self setNeedsDisplay];
}
}
- (void)setInsets:(CGSize)inInsets {
if(!CGSizeEqualToSize(_insets, inInsets)) {
_insets = inInsets;
[self setNeedsLayout];
[self setNeedsDisplay];
}
}
- (void)awakeFromNib {
[super awakeFromNib];
self.borderLayer = [CALayer new];
self.borderLayer.borderColor = [[UIColor blueColor] CGColor];
self.borderLayer.borderWidth = 0.5;
self.borderLayer.continuousCorners = YES;
self.borderLayer.cornerRadius = self.radius;
[self.layer addSublayer:self.borderLayer];
}
- (void)layoutSubviews {
[super layoutSubviews];
self.borderLayer.frame = CGRectInset(self.bounds, self.insets.width, self.insets.height);
}
- (void)drawRect:(CGRect)rect {
CGFloat theRadius = self.radius;
CGFloat theOffset = 1.2 * theRadius;
CGRect theRect = CGRectInset(self.bounds, self.insets.width, self.insets.height);
UIBezierPath *thePath = [UIBezierPath new];
CGPoint thePoint;
[thePath moveToPoint:CGPointMake(CGRectGetMinX(theRect) + theOffset, CGRectGetMinY(theRect))];
[thePath addLineToPoint:CGPointMake(CGRectGetMaxX(theRect) - theOffset, CGRectGetMinY(theRect))];
thePoint = CGPointMake(CGRectGetMaxX(theRect), CGRectGetMinY(theRect));
[thePath addQuadCurveToPoint:CGPointMake(CGRectGetMaxX(theRect), CGRectGetMinY(theRect) + theOffset) controlPoint:thePoint];
[thePath addLineToPoint:CGPointMake(CGRectGetMaxX(theRect), CGRectGetMaxY(theRect) - theOffset)];
thePoint = CGPointMake(CGRectGetMaxX(theRect), CGRectGetMaxY(theRect));
[thePath addQuadCurveToPoint:CGPointMake(CGRectGetMaxX(theRect) - theOffset, CGRectGetMaxY(theRect)) controlPoint:thePoint];
[thePath addLineToPoint:CGPointMake(CGRectGetMinX(theRect) + theOffset, CGRectGetMaxY(theRect))];
thePoint = CGPointMake(CGRectGetMinX(theRect), CGRectGetMaxY(theRect));
[thePath addQuadCurveToPoint:CGPointMake(CGRectGetMinX(theRect), CGRectGetMaxY(theRect) - theOffset) controlPoint:thePoint];
[thePath addLineToPoint:CGPointMake(CGRectGetMinX(theRect), CGRectGetMinY(theRect) + theOffset)];
thePoint = CGPointMake(CGRectGetMinX(theRect), CGRectGetMinY(theRect));
[thePath addQuadCurveToPoint:CGPointMake(CGRectGetMinX(theRect) + theOffset, CGRectGetMinY(theRect)) controlPoint:thePoint];
thePath.lineWidth = 0.5;
[[UIColor redColor] set];
[thePath stroke];
}
@end
希望这对您的问题有所帮助。我通过实验找到了 1.2
对 theOffset
的因数。如有必要,您可以修改此值。我为半径选择的值不是最佳值,当然可以改进。但由于它取决于与篮筐的确切距离,所以我没有投入太多时间。
自 iOS 13 起,有一个 API 可用于此:
https://developer.apple.com/documentation/quartzcore/calayercornercurve
见CALayerCornerCurve.continuous