Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UITableViewCell未按预期显示约束_Ios_Swift_Uitableview_Uikit - Fatal编程技术网

Ios UITableViewCell未按预期显示约束

Ios UITableViewCell未按预期显示约束,ios,swift,uitableview,uikit,Ios,Swift,Uitableview,Uikit,我试图以编程方式创建一个tableview单元格,但在按预期布局时遇到了一些问题。我认为这取决于我调用事物的顺序,但我无法按预期显示内容(我在uiview上尝试了插入和其他约束,它似乎工作正常) 我在VC中注册tableview单元格,我还在cellforrow中退出可重用单元格的队列,在这里我传递activity对象以更新单元格UI。该单元格的高度由heightforrow回调设置为300 活动单元代码 class ActivityCell: UITableViewCell {

我试图以编程方式创建一个tableview单元格,但在按预期布局时遇到了一些问题。我认为这取决于我调用事物的顺序,但我无法按预期显示内容(我在uiview上尝试了插入和其他约束,它似乎工作正常)

我在VC中注册tableview单元格,我还在cellforrow中退出可重用单元格的队列,在这里我传递activity对象以更新单元格UI。该单元格的高度由heightforrow回调设置为300

活动单元代码

class ActivityCell: UITableViewCell {
    
    private var activityCard = UIView()
    private var verticalStack = UIStackView()
    private var nameStack = UIStackView()      // top horizontal stack
    private let profileImage = UIImageView()
    private let profileNameLbl = UILabel()
    private let dateLbl = UILabel()
    private let raceVerticalStack = UIStackView()  //middle
    private let topRaceStack = UIStackView()
    private let bottomRaceStack = UIStackView()
    private let raceNameStack = UIStackView()
    private let raceNameLbl = UILabel()
    private let distanceStack = UIStackView()
    private let distanceLbl = UILabel()
    private let distanceValueLbl = UILabel()
    private let timeStack = UIStackView()
    private let timeLbl = UILabel()
    private let timeValueLbl = UILabel()
    private let paceStack = UIStackView()
    private let paceLbl = UILabel()
    private let paceValueLbl = UILabel()
    private let positionStack = UIStackView()
    private let positionLbl = UILabel()
    private let positionValueLbl = UILabel()
    private let pointsStack = UIStackView()
    private let pointsLbl = UILabel()
    private let pointsValueLbl = UILabel()
    private let bottomStack = UIStackView()  //bottom
    private let clapStack = UIStackView()
    private let clapIcon = UIImageView()
    private let clapCountLbl = UILabel()
    private let clapCommentStack = UIStackView()
    private let commentStack = UIStackView()
    private let commentIcon = UIImageView()
    private let commentCountLbl = UILabel()
    private let clapButton = UIButton()     // interaction buttons
    private let commentButton = UIButton()
    
    
    private let gradientStart = UIColor(red: 24/255, green: 44/255, blue: 86/255, alpha: 1.0)
    private let gradientEnd = UIColor(red: 234/255, green: 82/255, blue: 119/255, alpha: 1.0)
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        layer.masksToBounds = true
        self.contentView.layer.masksToBounds = true
        activityCard.frame = self.frame.inset(by: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))
        verticalStack.frame = activityCard.frame
        
        setupHierarchy()
        setConstraints()
        configureView()
        
    }
    
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func configureView() {
        labelSetup()
        buttonSetup()
        stackViewSetup()
        imageSetup()
        stackViewSetup()
        setShadow()
    }

    func updateCell(with activity: RaceActivity) {
        profileNameLbl.text = activity.runnerName
        profileImage.image = activity.profileImage
        raceNameLbl.text = activity.raceName
        distanceValueLbl.text = activity.distance
        timeValueLbl.text = activity.time
        paceValueLbl.text = activity.pace
        positionValueLbl.text = activity.position
        pointsValueLbl.text = activity.points
    }
    
    private func labelSetup() {
        profileNameLbl.font = .Graphik()
        raceNameLbl.font = .Graphik(.medium, size: 22)
        dateLbl.font = .Graphik(.light, size: 17)
        distanceLbl.font = .Graphik()
        timeLbl.font = .Graphik()
        paceLbl.font = .Graphik()
        positionLbl.font = .Graphik()
        pointsLbl.font = .Graphik()
        clapCountLbl.font = .Graphik()
        commentCountLbl.font = .Graphik()
        paceLbl.font = .Graphik()
        distanceValueLbl.font = .Graphik(.medium)
        timeValueLbl.font = .Graphik(.medium)
        paceValueLbl.font = .Graphik(.medium)
        positionValueLbl.font = .Graphik(.medium)
   
        timeLbl.textAlignment = .left
        paceLbl.textAlignment = .center
        paceValueLbl.textAlignment = .center
        pointsLbl.textAlignment = .left
        pointsValueLbl.textAlignment = .left
        dateLbl.textAlignment = .right
        clapCountLbl.text = "33"
        commentCountLbl.text = "12"
        positionLbl.text = "Position"
        pointsLbl.text = "Points"
        distanceLbl.text = "Distance"
        timeLbl.text = "Time"
        paceLbl.text = "Pace"
        dateLbl.text = "Friday"
    }
    
    private func stackViewSetup() {
        nameStack.distribution = .fillProportionally
        topRaceStack.distribution = .fillEqually
        bottomRaceStack.distribution = .fillEqually
        clapCommentStack.distribution = .fillEqually
        bottomStack.distribution = .fillEqually
        
        raceNameStack.axis = .horizontal
        nameStack.axis = .horizontal
        verticalStack.axis = .vertical
        raceVerticalStack.axis = .vertical
        bottomStack.axis = .horizontal
        topRaceStack.axis = .horizontal
        bottomRaceStack.axis = .horizontal
        distanceStack.axis = .vertical
        timeStack.axis = .vertical
        paceStack.axis = .vertical
        positionStack.axis = .vertical
        pointsStack.axis = .vertical
        
        nameStack.spacing = 10
        verticalStack.spacing = 5
        raceVerticalStack.spacing = 10
        bottomStack.spacing = 10
        
        nameStack.alignment = .center
        distanceStack.alignment = .center
        timeStack.alignment = .center
        paceStack.alignment = .center
        pointsStack.alignment = .center
        positionStack.alignment = .center
        clapCommentStack.alignment = .center
        bottomStack.alignment = .center
        
        raceVerticalStack.spacing = 5
        topRaceStack.spacing = 2
        clapCommentStack.spacing = 3
        clapStack.spacing = 4
        commentStack.spacing = 4
    }
    
    private func buttonSetup() {
        clapButton.setTitle("Clap", for: .normal)
        clapButton.setTitleColor(.darkGray, for: .normal)
        clapButton.titleLabel?.font = .Graphik(.regular, size: 14)
        clapButton.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        clapButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 30)
        clapButton.setImage(UIImage(named: "clap"), for: .normal)
        commentButton.setTitle("Comment", for: .normal)
        commentButton.setTitleColor(.darkGray, for: .normal)
        commentButton.titleLabel?.font = .Graphik(.regular, size: 14)
        commentButton.titleEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
        commentButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 10)
        commentButton.setImage(UIImage(named: "comment"), for: .normal)
    }
    
    private func imageSetup() {
        profileImage.layer.cornerRadius = 15
        profileImage.backgroundColor = .lightGray
        clapIcon.image = UIImage(named: "clapGrey")
        clapIcon.contentMode = .scaleAspectFit
        commentIcon.image = UIImage(named: "commentGrey")
        commentIcon.contentMode = .scaleAspectFit
    }
 
    
    private func setShadow() {

        let gradient = CAGradientLayer()
        gradient.frame =  CGRect(origin: CGPoint(x: 10, y: 5), size: frame.size)
        gradient.colors = [gradientStart.cgColor, gradientEnd.cgColor]

        let border = CAShapeLayer()
        border.lineWidth = 2
        border.path = UIBezierPath(roundedRect: frame.inset(by: UIEdgeInsets(top: 10, left: 2, bottom: 10, right: 22)), cornerRadius: 12).cgPath
        border.strokeColor = UIColor.black.cgColor
        border.fillColor = UIColor.clear.cgColor
        gradient.mask = border
        removeExistingGradient(from: self)
        self.layer.addSublayer(gradient)
        
    }
    
    private func setConstraints() {
        
        let constraints = [
            nameStack.heightAnchor.constraint(equalToConstant: 50),
            raceNameStack.heightAnchor.constraint(equalToConstant: 30),
            topRaceStack.heightAnchor.constraint(equalToConstant: 60),
            bottomRaceStack.heightAnchor.constraint(equalToConstant: 60),
            profileImage.heightAnchor.constraint(equalToConstant: 30),
            profileImage.widthAnchor.constraint(equalToConstant: 30),
            commentButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 90),
            clapButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 90),
            clapIcon.widthAnchor.constraint(equalToConstant: 15),
            commentIcon.widthAnchor.constraint(equalToConstant: 15),
        ]
        NSLayoutConstraint.activate(constraints)
        setupMargins()
    }
    
    private func setupMargins() {
        nameStack.layoutMargins = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 25)
        raceNameStack.layoutMargins = UIEdgeInsets(top:0, left: 20, bottom: 0, right: 0)
        raceVerticalStack.layoutMargins = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 35)
        bottomStack.layoutMargins = UIEdgeInsets(top: 0, left: 20, bottom: 10, right: 30)
        nameStack.isLayoutMarginsRelativeArrangement = true
        topRaceStack.isLayoutMarginsRelativeArrangement = true
        bottomRaceStack.isLayoutMarginsRelativeArrangement = true
        raceNameStack.isLayoutMarginsRelativeArrangement = true
        bottomStack.isLayoutMarginsRelativeArrangement = true
        addLines()
    }
    
    private func addLines() {
        guard bottomStack.frame.height > 0 else { return }
        let horizontalStart = CGPoint(x: bottomStack.frame.minX, y: bottomStack.frame.minY)
        let bottomLine = UIView(frame: CGRect(x: horizontalStart.x + 20, y: horizontalStart.y + 12, width: bottomStack.frame.width - 40, height: 1.0))
        bottomLine.tag = 99
        bottomLine.layer.borderWidth = 0.8
        bottomLine.layer.borderColor = UIColor.lightGray.cgColor

        let clapStackLine = UIView(frame: CGRect(x: clapCommentStack.frame.maxX, y: horizontalStart.y + 22, width: 1.0, height: clapCommentStack.frame.maxY - clapCommentStack.frame.minY))
        clapStackLine.layer.borderWidth = 0.8
        clapStackLine.layer.borderColor = UIColor.lightGray.cgColor
        let commentLine = UIView(frame: CGRect(x: clapButton.frame.maxX, y: horizontalStart.y + 22, width: 1.0, height: clapCommentStack.frame.maxY - clapCommentStack.frame.minY))
        commentLine.layer.borderWidth = 0.8
        commentLine.layer.borderColor = UIColor.lightGray.cgColor
        let topLine = UIView(frame: CGRect(x: horizontalStart.x + 20, y: nameStack.frame.maxY + 5, width: bottomStack.frame.width - 40, height: 1.0))
        topLine.layer.borderWidth = 0.8
        topLine.layer.borderColor = UIColor.lightGray.cgColor
        self.activityCard.addSubview(bottomLine)
        self.activityCard.addSubview(clapStackLine)
        self.activityCard.addSubview(commentLine)
        self.activityCard.addSubview(topLine)
    }
    
    
    private func setupHierarchy() {
        nameStack.addArrangedSubview(profileImage)
        nameStack.addArrangedSubview(profileNameLbl)
        nameStack.addArrangedSubview(dateLbl)
        
        raceVerticalStack.addArrangedSubview(raceNameStack)
        raceVerticalStack.addArrangedSubview(topRaceStack)
        raceVerticalStack.addArrangedSubview(bottomRaceStack)
        
        raceNameStack.addArrangedSubview(raceNameLbl)
        
        topRaceStack.addArrangedSubview(distanceStack)
        topRaceStack.addArrangedSubview(timeStack)
        topRaceStack.addArrangedSubview(paceStack)
        
        bottomRaceStack.addArrangedSubview(positionStack)
        bottomRaceStack.addArrangedSubview(pointsStack)
        bottomRaceStack.addArrangedSubview(UIView())
        
        distanceStack.addArrangedSubview(distanceLbl)
        distanceStack.addArrangedSubview(distanceValueLbl)
        timeStack.addArrangedSubview(timeLbl)
        timeStack.addArrangedSubview(timeValueLbl)
        paceStack.addArrangedSubview(paceLbl)
        paceStack.addArrangedSubview(paceValueLbl)
        positionStack.addArrangedSubview(positionLbl)
        positionStack.addArrangedSubview(positionValueLbl)
        pointsStack.addArrangedSubview(pointsLbl)
        pointsStack.addArrangedSubview(pointsValueLbl)
        
        clapStack.addArrangedSubview(clapIcon)
        clapStack.addArrangedSubview(clapCountLbl)
        
        commentStack.addArrangedSubview(commentIcon)
        commentStack.addArrangedSubview(commentCountLbl)
        
        clapCommentStack.addArrangedSubview(clapStack)
        clapCommentStack.addArrangedSubview(commentStack)
        
        mainStackHierarchy()
    }
    
    private func mainStackHierarchy() {
        bottomStack.addArrangedSubview(clapCommentStack)
        bottomStack.addArrangedSubview(clapButton)
        bottomStack.addArrangedSubview(commentButton)
        
        verticalStack.addArrangedSubview(nameStack)
        verticalStack.addArrangedSubview(raceNameStack)
        verticalStack.addArrangedSubview(raceVerticalStack)
        verticalStack.addArrangedSubview(bottomStack)
        activityCard.addSubview(verticalStack)
        self.contentView.addSubview(activityCard)
    }
}

当前输出的屏幕截图:


预期输出的屏幕截图:



感谢您的帮助:D

您遇到了问题,因为您使用了大量显式框架,而不是利用自动布局

首先,如果您将
init()
func更改为此并运行应用程序:

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    layer.masksToBounds = true
    self.contentView.layer.masksToBounds = true
    
    // no need to set frames
    //activityCard.frame = self.frame.inset(by: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))
    //verticalStack.frame = activityCard.frame
    
    setupHierarchy()
    setConstraints()
    configureView()

    activityCard.translatesAutoresizingMaskIntoConstraints = false
    verticalStack.translatesAutoresizingMaskIntoConstraints = false
    
    NSLayoutConstraint.activate([
        
        activityCard.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10.0),
        activityCard.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10.0),
        activityCard.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10.0),
        activityCard.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10.0),

        verticalStack.topAnchor.constraint(equalTo: activityCard.topAnchor, constant: 6.0),
        verticalStack.leadingAnchor.constraint(equalTo: activityCard.leadingAnchor, constant: 6.0),
        verticalStack.trailingAnchor.constraint(equalTo: activityCard.trailingAnchor, constant: -6.0),
        verticalStack.bottomAnchor.constraint(equalTo: activityCard.bottomAnchor, constant: -6.0),

    ])
    
}
你会发现你离你想要的更近了

接下来,改变:

private var activityCard = UIView()
致:

并使用该类:

class ActivityCardView: UIView {
    private let gradientStart = UIColor(red: 24/255, green: 44/255, blue: 86/255, alpha: 1.0)
    private let gradientEnd = UIColor(red: 234/255, green: 82/255, blue: 119/255, alpha: 1.0)

    private let gradLayer = CAGradientLayer()

    override init(frame: CGRect) {
        super.init(frame: frame)
        layer.addSublayer(gradLayer)
        gradLayer.colors = [gradientStart.cgColor, gradientEnd.cgColor]
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    override func layoutSubviews() {
        super.layoutSubviews()

        gradLayer.frame = bounds
        
        let border = CAShapeLayer()
        border.lineWidth = 2
        border.path = UIBezierPath(roundedRect: bounds.inset(by: UIEdgeInsets(top: 10, left: 2, bottom: 10, right: 2)), cornerRadius: 12).cgPath
        border.strokeColor = UIColor.black.cgColor
        border.fillColor = UIColor.clear.cgColor
        gradLayer.mask = border
    }
}
然后,从cell类中删除您的
private func setShadow()
。此
ActivityCardView
类将自动处理渐变边框

对于“分隔符”行,您最好将它们添加为
垂直堆栈的排列子视图,而不是尝试使用绝对坐标定位它们:

private func mainStackHierarchy() {
    bottomStack.addArrangedSubview(clapCommentStack)
    bottomStack.addArrangedSubview(clapButton)
    bottomStack.addArrangedSubview(commentButton)
    
    verticalStack.addArrangedSubview(nameStack)
    
    var hLineView = UIView()
    hLineView.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
    hLineView.backgroundColor = .lightGray
    verticalStack.addArrangedSubview(hLineView)
    
    verticalStack.addArrangedSubview(raceNameStack)
    verticalStack.addArrangedSubview(raceVerticalStack)

    hLineView = UIView()
    hLineView.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
    hLineView.backgroundColor = .lightGray
    verticalStack.addArrangedSubview(hLineView)
    
    verticalStack.addArrangedSubview(bottomStack)
    activityCard.addSubview(verticalStack)
    self.contentView.addSubview(activityCard)
}
此时,您的输出应该如下所示:

种族名称上的下划线可能最好通过使用带有下划线样式的属性文本来处理


我想您可能想对间距进行一些调整,但这应该不会有任何问题。

太棒了!非常感谢,我不敢相信我忽略了为活动卡创建一个新类。我想我是在考虑故事板设计而不是利用编程方式创建UI元素的优点
private func mainStackHierarchy() {
    bottomStack.addArrangedSubview(clapCommentStack)
    bottomStack.addArrangedSubview(clapButton)
    bottomStack.addArrangedSubview(commentButton)
    
    verticalStack.addArrangedSubview(nameStack)
    
    var hLineView = UIView()
    hLineView.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
    hLineView.backgroundColor = .lightGray
    verticalStack.addArrangedSubview(hLineView)
    
    verticalStack.addArrangedSubview(raceNameStack)
    verticalStack.addArrangedSubview(raceVerticalStack)

    hLineView = UIView()
    hLineView.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
    hLineView.backgroundColor = .lightGray
    verticalStack.addArrangedSubview(hLineView)
    
    verticalStack.addArrangedSubview(bottomStack)
    activityCard.addSubview(verticalStack)
    self.contentView.addSubview(activityCard)
}