圆化视图的右上角和左上角?

Posted

技术标签:

【中文标题】圆化视图的右上角和左上角?【英文标题】:Round out the top right and left corners of a view? 【发布时间】:2016-01-19 13:35:57 【问题描述】:

我正在尝试弄清楚如何屏蔽 UIView 以显示一个形状,该形状代表一个正方形,上面有一半的圆。

基本上,这就像仅对顶部两个角应用边框半径以将它们弄圆并创建弧线。

我正在使用 swift,这让我发疯。

编辑:CornerRadius 没有做我想做的事。我觉得我必须使用 CGShapeLayer,但我不确定如何创建弧线。

编辑2:

EDIT3:

考虑到解释我想要什么,提供图片,并解释我不明白我需要做什么,或者我需要如何做这对某些人来说还不够,以下是我尝试过的:

尝试设置layer.cornerRadius 属性,同时将视图的底部推到屏幕之外以隐藏底角以免出现截断,这种类型的遮罩过于圆形,无法提供正确的弧形结果。

我尝试使用UIBezierPath 设置顶部两个角以使用视图width / 2 的cornerRadii。这也没有产生适当的结果。在尝试将值硬编码到cornerRadii 中时,我注意到无论值如何,我似乎都无法获得我想要的结果。

还有哪些其他选择?还是我只是错误地使用了 BezierPath?

编辑 4:

这是我的原始代码。

override func viewWillAppear(animated: Bool) 
    super.viewWillAppear(animated)

    let bezierPath = UIBezierPath(roundedRect: navBarView.bounds, byRoundingCorners: [.TopLeft, .TopRight], cornerRadii: CGSizeMake(navBarView.bounds.width / 2, navBarView.bounds.width / 2)).CGPath;

    let shapeLayer = CAShapeLayer();
    shapeLayer.bounds = navBarView.bounds
    shapeLayer.path = bezierPath
    navBarView.layer.mask = shapeLayer

    updateUI() // <-- Label text, etc. 

另外,如前所述,曾尝试做navBarView.layer.cornerRadius = x

【问题讨论】:

你能展示你尝试过的代码以及你需要哪种类型的输出 看到这个:***.com/questions/22679886/… 添加了我想要完成的内容 我正在使用 swift,这让我发疯了。 代码在哪里? @vikingosegundo - 代码与下面发布的相同。我已经尝试使用cornerRadius 和 UIBezierPath 并且无法获得正确的结果。 【参考方案1】:

试试这个:

let path = UIBezierPath(roundedRect:self.view.bounds, byRoundingCorners:[.TopLeft, .TopRight], cornerRadii: CGSizeMake(20, 20))
    let maskLayer = CAShapeLayer()
    maskLayer.frame = self.view.bounds;
    maskLayer.path = path.CGPath
    self.view.layer.mask = maskLayer;

UIBezierPath 类允许您定义由直线段和曲线段组成的路径,并在自定义视图中呈现该路径。

    在 UIBezierPath 中生成路径的圆角 要生成 CAShapeLayer,请将其设置为路径之一 图层到您想要在一侧仅圆角 2 作为遮罩层的视图

示例:

let DynamicView=UIView(frame: CGRectMake(50, 200, 200, 300))
        DynamicView.backgroundColor=UIColor.redColor()
        let path = UIBezierPath(roundedRect:DynamicView.bounds, byRoundingCorners:[.TopLeft, .TopRight], cornerRadii: CGSizeMake(20, 20))
        let maskLayer = CAShapeLayer()
        maskLayer.frame = DynamicView.bounds;
        maskLayer.path = path.CGPath
        DynamicView.layer.mask = maskLayer;


        self.view.addSubview(DynamicView)

结果:

【讨论】:

您好 Ramesh,请在您的回答中添加更多详细信息,说明这如何为可能无法理解代码的未来受众解决此问题。 这个答案并不能解释任何事情,甚至改变半径值也没有给我想要的结果。无论单边的数字如何,它都会切入一点。我添加了我所追求的弧线的图像。也许我仍然做错了,我尝试将 raid 设置为 view / 2 的边界以及一些硬编码值 在您的代码中,您使用的是边界。这些可能会给出不同的结果。检查更新的答案 @Ramesh_T - 这是所提供答案的结果:i.imgur.com/Ncgvqvw.png 它也只影响左上角。 -- 更改硬编码值也不会调整遮罩的形状。 我在这里上传了示例应用程序:efshare.com/?s=L8N8MC。它对我来说很好。【参考方案2】:

没那么难,需要在视图的图层上加遮罩。请注意,添加蒙版会从蒙版本身中删除所有内容。 您应该注意的另一件事是,如果您的视图正在调整大小,则您的蒙版也需要调整,因为它不会自动更新路径。 假设您正在使用 SWIFT,您可以继承 UIView:

override func layoutSubviews() 
        super.layoutSubviews()
        maskLayer.frame = layer.bounds
        maskLayer.path = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.TopLeft, .TopRight], cornerRadii: CGSizeMake(bounds.size.widht/2, bounds.size.widht/2)).CGPath
    

    override init(frame: CGRect) 
        super.init(frame: frame)
        layer.mask = maskLayer

    

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        layer.mask = maskLayer
    

maskLayerCAShapeLayer,您必须将其创建为常量或惰性属性。 代码未经测试。

【讨论】:

这个答案的问题,以及下面的问题是我已经尝试过 UIBezier 路径(以及尝试了你的两种解决方案,它们最终是相同的)。结果与使用 layer.cornerRadius 属性没有什么不同。 您确定删除了旧的 corenrRadius 设置吗?为了更好地理解你想要什么,你能贴一张小图吗? 该图是主帖中的图片,我确定我已经删除了圆角半径设置,【参考方案3】:

您好,在通过调度队列调整视图大小后,我遇到了同样的问题

    self.lblShortDescription.frame = CGRectMake(self.lblShortDescription.frame.origin.x, self.lblShortDescription.frame.origin.y, width, self.lblShortDescription.requiredHeight()) // here required height is the function to resize the label according to the content.
    dispatch_async(dispatch_get_main_queue(), 
                self.viewTopTitaleBack.round([UIRectCorner.TopLeft, UIRectCorner.TopRight], radius: 8.0) // here rounding is again a function I used for rounding the view by passing the parameters.
            );


extension UILabel
    func requiredHeight() -> CGFloat
        let label:UILabel = UILabel(frame: CGRectMake(0, 0, self.frame.width, CGFloat.max))
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.ByWordWrapping
        label.font = self.font
        label.text = self.text
        label.sizeToFit()
        return label.frame.height
    


extension UIView 

    func round(corners: UIRectCorner, radius: CGFloat) -> CAShapeLayer 
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.CGPath
        self.layer.mask = mask
        return mask
    


希望这会有所帮助。

【讨论】:

【参考方案4】:

测试并尝试了Ramesh_T 的answer,它可以完美地添加 .clipsToBounds 为真。就像一个魅力,特别是如果嵌套在一个扩展函数中,例如:

SWIFT 3

extension UIView 
  func roundCorners(_ corner: UIRectCorner,_ radii: CGFloat) 
      let maskLayer = CAShapeLayer()
      maskLayer.frame = self.layer.bounds
      maskLayer.path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corner, cornerRadii: CGSize(width: radii, height: radii)).cgPath
    
      self.layer.mask = maskLayer
      layer.masksToBounds = true
  

这样调用来圆特定视图的左上角和右上角:

someView.roundCorners([.topRight,.topLeft], 60)

编辑

但是,查看 UIBezierPath(roundedRect..) 的方法声明: 似乎角半径被最大化到视图高度或宽度的一半,以较小者为准...

【讨论】:

以上是关于圆化视图的右上角和左上角?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Iphone +上仅将表格视图自定义单元格的左上角和右上角半径转角

在约束布局中拖放视图将视图移动到左上角

在左上角的视图上反应原生视图?

在 iOS 上的动画期间防止视图从左上角弹出

如何将复合可绘制对象放在文本视图的左上角

Storyboard xib 实时视图在左上角呈现所有子视图