Ios 在UITableViewCell内的不同大小的UIView上放置遮罩层

Ios 在UITableViewCell内的不同大小的UIView上放置遮罩层,ios,swift,uitableview,uibezierpath,cashapelayer,Ios,Swift,Uitableview,Uibezierpath,Cashapelayer,我有一个UITableView,其单元格包含一个子视图,我需要在该子视图上执行三项操作: 根据特定于此单元格的对象内的值,在运行时更改其宽度约束 根据相同的值更改其背景色 环绕视图的左上角和左下角,但保持其右侧的角不变(因此图层。拐角半径不是选项) 我在自定义的UITableViewCell子类中使用以下代码,仅在视图的一侧实现圆角效果,我从tableView:cellForRowAt:调用它: func roundLeadingEdgesOfBar() { let roundedLay

我有一个
UITableView
,其单元格包含一个子视图,我需要在该子视图上执行三项操作:

  • 根据特定于此单元格的对象内的值,在运行时更改其宽度约束
  • 根据相同的值更改其背景色
  • 环绕视图的左上角和左下角,但保持其右侧的角不变(因此
    图层。拐角半径
    不是选项)
  • 我在自定义的
    UITableViewCell
    子类中使用以下代码,仅在视图的一侧实现圆角效果,我从
    tableView:cellForRowAt:
    调用它:

    func roundLeadingEdgesOfBar() {
        let roundedLayer = CAShapeLayer()
        roundedLayer.bounds = viewInQuestion.frame
        roundedLayer.position = viewInQuestion.center
        roundedLayer.path = UIBezierPath(roundedRect: viewInQuestion.bounds,
                                         byRoundingCorners: [.topLeft, .bottomLeft],
                                         cornerRadii: CGSize(width: 2, height: 2)).cgPath
        viewInQuestion.layer.mask = roundedLayer
        print("frame: \(viewInQuestion.frame)")
    }
    
    但是,我运行此代码时看到的效果如下:

    上述代码中的
    print
    语句产生以下输出,表明
    viewInQuestion
    每次在屏幕上清晰显示时都具有相同的帧:

    frame: (175.0, 139.5, 200.0, 5.0)
    frame: (175.0, 139.5, 200.0, 5.0)
    frame: (175.0, 139.5, 200.0, 5.0)
    frame: (175.0, 139.5, 200.0, 5.0)
    
    因此,我假设在调用此函数时,视图上的宽度约束尚未渲染。当我向上滚动整个表格视图,直到所有单元格都不在视图中,然后再将它们重新滚动到视图中时,一切看起来都是正确的,打印的帧都是不同的,正如我所期望的:

    frame: (136.5, 79.5, 238.5, 5.0)
    frame: (169.5, 79.5, 205.5, 5.0)
    frame: (226.0, 79.5, 149.0, 5.0)
    frame: (247.5, 79.5, 127.5, 5.0)
    
    我已经读了好几遍,以便执行依赖于从
    layoutSubviews
    中应用的约束的代码,但这给了我相同的结果。我甚至试着从
    tableView:willDisplay:forRowAt:
    中调用
    roundleadingesofbar
    ,但都没有用

    我还发现,这建议将掩码层代码放在
    drawRect:
    中。这实际上为我解决了99%的问题(将性能问题放在一边),但在很长的表视图中仍然存在一些角落案例(没有双关语),我仍然看到错误的行为

    我最后的办法是通过
    performSelector
    调用舍入函数,延迟为0.00001,其工作原理是,在屏幕上看到缺陷大约一秒钟后,它就消失了——这离理想的行为还很远,更不用说我为它编写的糟糕代码了


    是否有任何方法可以使用正确的运行时框架在
    UITableViewCell
    内的视图上可靠地应用形状层?

    我认为您应该做的是

  • cellforrowatinexpath
    中设置与当前对象相关的属性,尝试在该特定值的setter中设置约束
  • 调用
    setNeedsLayout
    ,它将在将来调用
    LayoutFeeded
    ->
    LayoutSubview
  • 布局子视图中设置圆角

  • 我希望这会对你有所帮助。

    我认为你应该做的是

  • cellforrowatinexpath
    中设置与当前对象相关的属性,尝试在该特定值的setter中设置约束
  • 调用
    setNeedsLayout
    ,它将在将来调用
    LayoutFeeded
    ->
    LayoutSubview
  • 布局子视图中设置圆角

  • 我希望这将对您有所帮助。

    我建议创建一个
    UIView
    子类,让它来处理舍入操作,而不是调用函数“舍入边”

    例如:

    class BulletBar: UIView {
    
        override func layoutSubviews() {
    
            let roundedLayer = CAShapeLayer()
    
            roundedLayer.frame = bounds
    
            roundedLayer.path = UIBezierPath(roundedRect: bounds,
                                             byRoundingCorners: [.topLeft, .bottomLeft],
                                             cornerRadii: CGSize(width: 2, height: 2)).cgPath
            layer.mask = roundedLayer
    
        }
    
    }
    
    现在,将单元格中“bar”子视图的类设置为BulletBar。使用约束将其固定到右侧和底部,并约束高度和宽度。为宽度约束创建一个
    IBOutlet
    ,然后根据需要设置
    barWidthConstraint.constant

    类本身将处理圆角

    结果:


    我建议创建一个
    UIView
    子类,让它处理舍入操作,而不是调用函数“舍入边”

    例如:

    class BulletBar: UIView {
    
        override func layoutSubviews() {
    
            let roundedLayer = CAShapeLayer()
    
            roundedLayer.frame = bounds
    
            roundedLayer.path = UIBezierPath(roundedRect: bounds,
                                             byRoundingCorners: [.topLeft, .bottomLeft],
                                             cornerRadii: CGSize(width: 2, height: 2)).cgPath
            layer.mask = roundedLayer
    
        }
    
    }
    
    现在,将单元格中“bar”子视图的类设置为BulletBar。使用约束将其固定到右侧和底部,并约束高度和宽度。为宽度约束创建一个
    IBOutlet
    ,然后根据需要设置
    barWidthConstraint.constant

    类本身将处理圆角

    结果:


    setNeedsLayout
    设置未来对
    layoutSubviews
    的调用,尝试从设置属性的点显式调用
    layoutSubviews
    。我已经尝试显式调用
    layoutSubviews
    (未成功),我猜这是因为在我配置单元格时,约束没有呈现,因此调用
    layoutSubviews
    将没有任何意义,这一定是我无法发现的问题。我想尝试将代码移动到
    updateConstraints()
    并调用
    setNeedsUpdateConstraints()
    setNeedsLayout
    设置对
    布局子视图的未来调用,尝试从设置属性的点显式调用
    layoutSubviews
    。我已经尝试显式调用
    layoutSubviews
    (没有成功),我想这是因为在配置单元格的点上没有呈现约束,因此,调用
    layoutSubviews
    将毫无意义,其中一定存在一些我无法发现的问题。我想试着将代码移动到
    updateConstraints()
    并调用
    setNeedsUpdateConstraints()
    是您在单元格的子视图中遇到问题的视图吗?如果是这样,如果您没有设置图层遮罩,大小/位置是否正确?@DonMag是的,这是一个子视图,否,如果我没有设置图层遮罩,所有单元格的输出帧都是相同的错误帧(但屏幕上的一切都是正确的)确定-请参阅我的答案,看看这是否对你有用。你的手机子视图有问题吗?如果是,如果不设置图层遮罩,大小/位置是否正确?@DonMag是的,它是一个子视图,并且