实际上复制/提取 Apple 的 "continuous corners for iPhoneX"?

Actually duplicate / extract Apple's "continuous corners for iPhoneX"?

iPhoneX 的不寻常底角是 Apple 的新 (2017) “iPhoneX 的连续角”.

对于任何有经验的 iOS 程序员来说 近似 曲线是微不足道的,但是:

有没有人确切地知道如何实现这些,就像 Apple 所做的那样?

即使是私人电话,也知道就好了。

Apple 没有解释这一点似乎很奇怪。

请注意“近似”曲线是微不足道的:

重复,

  1. 对于任何有经验的 iOS 程序员来说 近似 曲线是微不足道的。

  2. 这里要问的问题具体是苹果是怎么做到的?

请不要再post任何向初学者展示如何绘制曲线和近似iPhone曲线的答案。

由于 @Aflah Bhari 的 评论,我写了一个实验性的 class,它构建了一个与 CALayer 的边界重叠的贝塞尔曲线路径。该层已将其私有 属性 continuousCorners 设置为 YES。这是结果:

图层的边框是蓝色,路径的颜色是红色。

这是代码。您可以在 Interface Builder 的属性检查器中设置 radiusinsets。我通过将视图控制器视图的 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.2theOffset 的因数。如有必要,您可以修改此值。我为半径选择的值不是最佳值,当然可以改进。但由于它取决于与篮筐的确切距离,所以我没有投入太多时间。

自 iOS 13 起,有一个 API 可用于此:

https://developer.apple.com/documentation/quartzcore/calayercornercurve

CALayerCornerCurve.continuous