簡體   English   中英

Tableview 單元格邊框在 swift 中未占據全寬

[英]Tableview cell border not occupying full width in swift

我正在嘗試在我的表格視圖單元格的所有邊上添加一個邊框,我能夠添加邊框,但面臨一個問題,即右側的邊框沒有占據單元格的整個寬度,如下面的屏幕截圖所示。 單元格邊框似乎采用了設置 storyboard UI 的初始寬度,例如,我已將 UI 設置為 iPhone SE,但如果我在 iPhone 11 上運行,則會出現此問題。 似乎是布局未刷新的一些問題。 我嘗試添加 setNeedsLayout、setNeedsDisplay 和 layoutSubviews,但它們似乎都不起作用。

在此處輸入圖像描述

Storyboard布局

在此處輸入圖像描述

以下是完整代碼

class ViewController: UIViewController {

    var dataSource = [String] ()
    override func viewDidLoad() {
        super.viewDidLoad()
        for index in 1...10 {
            dataSource.append("Cell value \(index)")
        }
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell: MyTableViewCell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCell", for: indexPath) as? MyTableViewCell else{return UITableViewCell()}
        
        cell.titleLabel.text = dataSource[indexPath.row]
        
        if indexPath.row == 0 {
            cell.containerView.addBorder(toEdges: [.left, .top, .right], color: .gray, thickness: 1.0)
        } else if indexPath.row == dataSource.count - 1 {
            cell.containerView.addBorder(toEdges: .all, color: .gray, thickness: 1.0)
        } else {
            cell.containerView.addBorder(toEdges: [.left, .top, .right], color: .gray, thickness: 1.0)
        }
        return cell
    }
}

class MyTableViewCell: UITableViewCell {
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var containerView: UIView!
}

extension UIView {
    func addBorder(toEdges edges: UIRectEdge, color: UIColor, thickness: CGFloat) {
        func addBorder(toEdge edges: UIRectEdge, color: UIColor, thickness: CGFloat) {
            let border = CALayer()
            border.backgroundColor = color.cgColor
            switch edges {
            case .top:
                border.frame = CGRect(x: 0, y: 0, width: frame.width, height: thickness)
            case .bottom:
                border.frame = CGRect(x: 0, y: frame.height - thickness, width: frame.width, height: thickness)
            case .left:
                border.frame = CGRect(x: 0, y: 0, width: thickness, height: frame.height)
            case .right:
                border.frame = CGRect(x: frame.width - thickness, y: 0, width: thickness, height: frame.height)
            default:
                break
            }
            layer.addSublayer(border)
        }
        
        if edges.contains(.top) || edges.contains(.all) {
            addBorder(toEdge: .top, color: color, thickness: thickness)
        }
        
        if edges.contains(.bottom) || edges.contains(.all) {
            addBorder(toEdge: .bottom, color: color, thickness: thickness)
        }
        
        if edges.contains(.left) || edges.contains(.all) {
            addBorder(toEdge: .left, color: color, thickness: thickness)
        }
        
        if edges.contains(.right) || edges.contains(.all) {
            addBorder(toEdge: .right, color: color, thickness: thickness)
        }
    }
}

您可能會發現使用UIView子類來處理“邊緣”要容易得多。

將此 class 添加到您的項目中:

class BorderedView: UIView {
    
    var edges: UIRectEdge = []
    var color: UIColor = .clear
    var thickness: CGFloat = 0
    
    var shapeLayer: CAShapeLayer!
    
    override class var layerClass: AnyClass {
        return CAShapeLayer.self
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        shapeLayer = self.layer as? CAShapeLayer
        shapeLayer.fillColor = UIColor.clear.cgColor
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        let pth = UIBezierPath()
        
        if edges.contains(.top) || edges.contains(.all) {
            pth.move(to: CGPoint(x: bounds.minX, y: bounds.minY))
            pth.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
        }
        
        if edges.contains(.bottom) || edges.contains(.all) {
            pth.move(to: CGPoint(x: bounds.minX, y: bounds.maxY))
            pth.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
        }
        
        if edges.contains(.left) || edges.contains(.all) {
            pth.move(to: CGPoint(x: bounds.minX, y: bounds.minY))
            pth.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY))
        }
        
        if edges.contains(.right) || edges.contains(.all) {
            pth.move(to: CGPoint(x: bounds.maxX, y: bounds.minY))
            pth.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
        }

        shapeLayer.lineWidth = thickness
        shapeLayer.strokeColor = color.cgColor
        shapeLayer.path = pth.cgPath
    }
}

然后將您的containerView的 Custom Class 分配給BorderedView 在您的單元 class 中正常連接它:

@IBOutlet weak var containerView: BorderedView!

將您的單元格 class 更改為:

class MyTableViewCell: UITableViewCell {
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var containerView: BorderedView!
    
    func configureContainer(toEdges edges: UIRectEdge, color: UIColor, thickness: CGFloat) -> Void {
        containerView.edges = edges
        containerView.color = color
        containerView.thickness = thickness
    }

}

然后,在cellForRowAt中,而不是調用:

cell.containerView.addBorder(toEdges: [.left, .top, .right], color: .gray, thickness: 1.0)

像這樣稱呼它:

cell.configureContainer(toEdges: [.left, .top, .right], color: .gray, thickness: 1.0)

結果 - 表格視圖在每側插入 8 分,因此您可以看到左/右邊緣:

在此處輸入圖像描述

當 tableView/cells 改變大小時(比如在設備旋轉時),邊緣會自動更新:

在此處輸入圖像描述

我同意@Asperi 的回答。 要么你必須繼承它並在drawrect中編寫這個方法。 或者為了快速解決方案,將 frame.width 更改為 UIScreen.main.bounds.width.Check 它將適用於您當前的要求和當前代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM