首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用nibs ( .xib)和Swift 5/Xcode11.3的iOS (9+)中的视图半径不一致

使用nibs ( .xib)和Swift 5/Xcode11.3的iOS (9+)中的视图半径不一致
EN

Stack Overflow用户
提问于 2020-01-04 02:47:16
回答 2查看 210关注 0票数 1

我有一个聊天应用程序与Xcode11.3编译为iOS 9.0+,并希望显示聊天气泡与3“半径12”角和一个“半径3”角。视图上的“角半径”设置为3,因此如果没有任何更改,视图的所有四个角的半径都设置为3。这些视图位于tableView的单元格中。正确设置三个较大的半径后,聊天气泡应该如下所示:

这里是笔尖:

以及在创建新的聊天气泡并填充文本时使用视图扩展添加半径的代码:

代码语言:javascript
复制
@IBDesignable
class ChatSent: NibDesignable {
    @IBOutlet weak var itemText: UILabel!
    @IBOutlet weak var itemBubbleSent: UIView!

    @IBInspectable
    public var Text: String = "" {
        didSet {
            self.itemText.text = Text
            itemBubbleSent.roundSentCorners([.topLeft, .topRight, .bottomLeft], radius: 12)
        }
    }
}

extension UIView {
    func roundSentCorners(_ corners:UIRectCorner, radius: CGFloat) {
    let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
    let mask = CAShapeLayer()
    mask.path = path.cgPath
    self.layer.mask = mask
  }
}

在主视图控制器中,聊天气泡中的文本设置如下:

代码语言:javascript
复制
let cell = tableView.dequeueReusableCell(withIdentifier: "Chat Sent", for: indexPath) as! ChatViewSentCellView
cell.myChatViewSent.Text = self.messageData[self.messageIndex!].messages[indexPath.item - 10]

所以,问题是半径角没有正确创建。它们始终不一致,这意味着当载入视图时,每个编号上都会发生相同的错误。此外,通过向上和向下滚动,可以使气泡正确地绘制,只有当向上滚动到下一组气泡时才返回到不正确的显示。请注意,有些角的半径错误或没有半径,并且有些气泡发生了偏移:

这是怎么回事?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-04 03:47:49

您的问题出在传递给函数的frame中,因为单元格还没有计算它的布局,所以您应该这样做:

首先:

代码语言:javascript
复制
let cell = tableView.dequeueReusableCell(withIdentifier: "Chat Sent", for: indexPath) as! ChatViewSentCellView
cell.myChatViewSent.text = self.messageData[self.messageIndex!].messages[indexPath.item - 10]

然后在您的自定义表格单元格类中:

代码语言:javascript
复制
class CellWithCustomLayout: UITableViewCell {
    override func layoutSubviews() {
        super.layoutSubviews()
        itemBubbleSent.layoutIfNeeded()
        //Mask your view with the path here, the view has the proper frame now, i.e:
        itemBubbleSent.roundSentCorners([.topLeft, .topRight, .bottomLeft], radius: 12)
    }
}

您可以更改代码以满足您的需要,但通常在执行viewDidLayoutSubviewslayoutSubviews之后,会计算出框架并准备就绪。

票数 3
EN

Stack Overflow用户

发布于 2020-01-04 04:06:51

我举的这个例子绝对不是实现这一点的最有效的方法,正如其他人所提到的,你的问题似乎与在一切布局之前绘制的视图有关-因此框架并不一致。如果你在显示视图之前知道视图的大小,我给出的这个例子可能会对你有所帮助,如果你想要制作一个像iMessage中看到的带有小弯曲尾巴的自定义语音气泡,它也会非常有帮助(显然这需要更多的路径计算,但如果你知道一些基本的三角/几何应该是非常容易的)。这是一个硬编码的例子,不会对右下角进行舍入:

代码语言:javascript
复制
func makePath(for bubbleView: UIView, with cornerRadius: CGFloat) -> UIBezierPath {
    let path = UIBezierPath()
    let height = bubbleView.frame.height
    let width = bubbleView.frame.width
    let π = CGFloat.pi
    // The (0,0) coordinate for a UIBezierPath starts off at the top left corner, not the bottom left like you'd think back in math class.
    let startPoint = CGPoint(x: 0, y: height/2)
    path.move(to: startPoint)
    // Draw the line up to where the corner would start
    path.addLine(to: CGPoint(x: 0, y: cornerRadius))
    // Add the top left corner
    path.addArc(withCenter: CGPoint(x: cornerRadius, y: cornerRadius), radius: cornerRadius, startAngle: π, endAngle: 3*π/2, clockwise: true)
    // Draw to the top right corner
    path.addLine(to: CGPoint(x: width-cornerRadius, y: 0))
    // Draw the top right corner
    path.addArc(withCenter: CGPoint(x: width-cornerRadius, y: cornerRadius), radius: cornerRadius, startAngle: 3*π/2, endAngle: 0, clockwise: true)
    // Draw line to the bottom right (no rounded corner)
    path.addLine(to: CGPoint(x: width, y: height))
    // If you wanted to round this corner you would add the commented out arc below
    //path.addArc(withCenter: CGPoint(x: width-cornerRadius, y: height-cornerRadius), radius: cornerRadius, startAngle: 0, endAngle: π/2, clockwise: true)

    // Draw line to the bottom left corner
    path.addLine(to: CGPoint(x: cornerRadius, y: height))
    // Draw the bottom left corner
    path.addArc(withCenter: CGPoint(x: cornerRadius, y: height-cornerRadius), radius: cornerRadius, startAngle: π/2, endAngle: π, clockwise: true)
    // End the line drawing back to the starting point
    path.addLine(to: startPoint)
    return path
}

对我来说,它产生了这样的结果:

您还应该能够看到如何轻松地添加一些参数和switch语句来自定义此方法,以裁剪多个角,或改变哪个角获得裁剪后的尾部

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59583775

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档