实际上复制/提取Apple的“iPhoneX的连续角落”?

时间:2018-03-11 12:29:09

标签: ios uibezierpath iphone-x

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

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

有没有人确切知道如何实现这些目标,就像Apple一样?

即使是私人电话,也不例外。

苹果没有解释这一点似乎非常奇怪。

enter image description here

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

重复,

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

  2. 问题在这里具体是指Apple实际上该怎么办?

  3. 拜托,拜托,请不要再发布任何答案,向初学者展示如何绘制曲线和近似iPhone曲线。

2 个答案:

答案 0 :(得分:2)

我写了一个实验课,它构造了一条bezier路径,该路径由于 @Aflah Bhari的评论而与CALayer的边界重叠。该图层已将其私有属性continuousCorners设置为YES。这是结果:

Layer and Path

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

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

答案 1 :(得分:1)

从iOS 13开始,有一个可用的API:

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

请参见CALayerCornerCurve.continuous