ios - 如何在 IOS 中修整可调整大小的 UIView 的一个角?

标签 ios calayer

我正在使用这段代码来修整我的 UIView 的一个角:

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:
    self.view.bounds byRoundingCorners:(UIRectCornerTopLeft) cornerRadii:
    CGSizeMake(10.0, 10.0)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.view.bounds;
maskLayer.path = maskPath.CGPath;
self.view.layer.mask = maskLayer;
self.view.layer.masksToBounds = NO;

只要我不调整 View 大小,这段代码就可以工作。如果我放大 View ,则不会出现新区域,因为它位于 mask 层的边界之外(此 mask 层不会随 View 自动调整自身大小)。我可以把面具做得尽可能大,但它可能在 iPad 上是全屏的,所以我担心这么大的面具的性能(我会有不止一个这样的面具)界面)。此外,超大尺寸的 mask 不适用于我需要将上角(单独)四舍五入的情况。

有没有更简单、更容易的方法来实现这一点?

更新:这是我要实现的目标:http://i.imgur.com/W2AfRBd.png (我想要的圆角在这里用绿色圈起来了)。

我已经实现了这个的工作版本,使用 UINavigationController 的子类并重写 viewDidLayoutSubviews,如下所示:

- (void)viewDidLayoutSubviews {
    CGRect rect = self.view.bounds;
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:rect 
        byRoundingCorners:UIRectCornerTopLeft cornerRadii:CGSizeMake(8.0, 8.0)];
    self.maskLayer = [CAShapeLayer layer];
    self.maskLayer.frame = rect;
    self.maskLayer.path = maskPath.CGPath;
    self.view.layer.mask = self.maskLayer;
}

然后我用我的 View Controller 实例化我的 UINavigationController 子类,然后我将导航 Controller View 的框架偏移 20 像素 (y) 以显示状态栏并留下 44 像素高的导航栏,如图所示。

该代码可以正常工作,只是它根本不能很好地处理旋转。当应用程序旋转时,viewDidLayoutSubviews 在旋转之前 被调用,我的代码创建一个适合 View 的 mask 旋转之后;这对旋转产生了不希望的 block 效应,在旋转过程中,本应隐藏的位会暴露出来。此外,虽然应用的旋转在没有此 mask 的情况下非常平滑,但在创建 mask 后旋转变得明显不稳定和缓慢。

iPad 应用程序 Evomail 也有这样的圆角,他们的应用程序也有同样的问题。

最佳答案

问题是,CoreAnimation 属性不会在 UIKit 动画 block 中进行动画处理。您需要创建一个单独的动画,它与 UIKit 动画具有相同的曲线和持续时间。

我在 viewDidLoad 中创建了 mask 层。当 View 即将布局时,我只修改了 mask 层的path属性。

您不知道布局回调方法中的旋转持续时间,但您在旋转之前(以及触发布局之前)知道它,因此您可以将其保留在那里。

下面的代码运行良好。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    //Keep duration for next layout.
    _duration = duration;
}

-(void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    UIBezierPath* maskPath = [UIBezierPath bezierPathWithRoundedRect:self.view.bounds byRoundingCorners:UIRectCornerTopLeft cornerRadii:CGSizeMake(10, 10)];

    CABasicAnimation* animation;

    if(_duration > 0)
    {
        animation = [CABasicAnimation animationWithKeyPath:@"path"];
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

        [animation setDuration:_duration];
        //Set old value
        [animation setFromValue:(id)((CAShapeLayer*)self.view.layer.mask).path];
        //Set new value
        [animation setToValue:(id)maskPath.CGPath];
    }
    ((CAShapeLayer*)self.view.layer.mask).path = maskPath.CGPath;

    if(_duration > 0)
    {
        [self.view.layer.mask addAnimation:animation forKey:@"path"];
    }

    //Zero duration for next layout.
    _duration = 0;
}

关于ios - 如何在 IOS 中修整可调整大小的 UIView 的一个角?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21298335/

相关文章:

ios - 重新设计的 iTunes Connect 中的崩溃报告

ios - 添加我的第一个 pod

objective-c - 不透明度渐变应用于 CALayer?

ios - 如何屏蔽和添加阴影到 UIView

ios - 如何以编程方式检查方向是否在 iOS 上被锁定 - Swift

iOS 使用 "Container View"且 View 数量未知

ios - Swift 中自定义属性的隐式 CALayer 动画

ios - 在 iOS 中使用 Core 动画打开纸张动画

iphone - CALayer 不渲染或绘图

iphone - 是否有一种简单的方法来访问 protected 目录中的URL?