簡體   English   中英

UIStackView內的NSLayout約束無法同時滿足約束

[英]NSLayout Constraint inside UIStackView Unable to simultaneously satisfy constraints

我正在以編程方式在 UITableViewCell 內創建 UIStackView。 StackView 包含 3 個消息氣球,由容器 UIView、UIImageView 和 UILabel 組成。 我正在嘗試使容器視圖的高度大於圖像視圖,因為它應該在 UIImageView 的頂部包含更多元素,但高度降低到 UIImageView 的高度,並且控制台顯示Unable to simultaneously satisfy constraints . 這個答案中獲得建議我將 UIImageView 的 translateAutoResizingMAskIntoConstraints 設置為 false,所以現在容器視圖確實比圖像視圖高,但圖像視圖的寬度不適合 UILabel。

messageView.translatesAutoresizingMaskIntoConstraints = true(默認)

messageView.translatesAutoresizingMaskIntoConstraints = false

編碼:

import UIKit
import PureLayout

@objc class ChatCell: UITableViewCell {

@IBOutlet weak var view: UIView!
@IBOutlet weak var headerView: UIView!
@IBOutlet weak var showMoreButton: UIButton!


override func awakeFromNib() {
    super.awakeFromNib()
    
    // stack view
    let stackView = UIStackView()
    stackView.axis = NSLayoutConstraint.Axis.vertical
    stackView.distribution = UIStackView.Distribution.equalSpacing
    stackView.alignment = UIStackView.Alignment.center
    stackView.spacing = 16.0
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    // bubble colors
    var colors = [UIColor]()
    colors.append(UIColor(red: 30/255, green: 222/255, blue: 38/255, alpha: 1))
    colors.append(UIColor(red: 20/255, green: 80/255, blue: 210/255, alpha: 1))
    colors.append(UIColor(red: 150/255, green: 120/255, blue: 30/255, alpha: 1))
    
    for color in colors {
        stackView.addArrangedSubview(addMessage(color: color, text: "לורם איפסום דולור סיט אמט, קונסקטורר אדיפיסינג אלית קולורס מרגשי ומרגשח. עמחליף לורם איפסום דולור סיט אמט, קונסקטורר אדיפיסינג אלית. סת אלמנקום ניסי נון ניבאה."))
    }
    
    view.addSubview(stackView)
    stackView.autoPinEdge(.top, to: .bottom, of: headerView, withOffset: 30)
    stackView.autoPinEdge(.bottom, to: .top, of: showMoreButton, withOffset: -30)
    stackView.autoCenterInSuperview()
}

func addMessage(color: UIColor, text: String) -> UIView {
    let containerView = UIView(frame: .zero)
    let label = UILabel()
    var messageView = UIImageView()
    
    setText(label, text)
    setTextBubble(label, &messageView, color)
    
    containerView.addSubview(messageView)

    containerView.translatesAutoresizingMaskIntoConstraints = false
    
    containerView.autoMatch(.width, to: .width, of: messageView)
    containerView.autoPinEdge(.bottom, to: .bottom, of: messageView)
    containerView.autoPinEdge(.top, to: .top, of: messageView, withOffset: -20)
    containerView.autoAlignAxis(.horizontal, toSameAxisOf: messageView)
    containerView.backgroundColor = .red
    
    label.center = messageView.center
    containerView.addSubview(label)
    view.addSubview(containerView)
    
    return containerView
}

fileprivate func setText(_ label: UILabel, _ text: String) {
    label.numberOfLines = 2
    label.font = UIFont.init(name: "South-Light", size: 18)
    label.textColor = .white
    label.text = text
    label.textAlignment = NSTextAlignment.right
    
    // set text frame
    let TEXT_FRAME_HEIGHT = 60.0
    let constraintRect = CGSize(width: 0.66 * Double(view.frame.width), height: TEXT_FRAME_HEIGHT)
    let boundingBox = text.boundingRect(with: constraintRect,
                                        options: .usesLineFragmentOrigin,
                                        attributes: [.font: label.font],
                                        context: nil)
    label.frame.size = CGSize(width:ceil(boundingBox.width),
                              height: ceil(boundingBox.height))
}

fileprivate func setTextBubble(_ label: UILabel, _ messageView: inout UIImageView, _ color: UIColor) {
    // set text bubble
    let bubbleImageSize = CGSize(width: label.frame.width + 28,
                                 height: label.frame.height + 20)
    
    messageView = UIImageView(frame:
        CGRect(x: 0,
               y: 0,//view.frame.height - bubbleImageSize.height - 5,
            width: bubbleImageSize.width,
            height: bubbleImageSize.height))
    
    let bubbleImage = UIImage(named: "incoming-message-bubble")?
        .resizableImage(withCapInsets: UIEdgeInsets(top: 17, left: 21,
                                                    bottom: 17, right: 21), resizingMode: .stretch)
        .withRenderingMode(UIImage.RenderingMode.alwaysTemplate)
    
    messageView.image = bubbleImage
    messageView.tintColor = color
    // this line changes layout
    messageView.translatesAutoresizingMaskIntoConstraints = false
}
}

控制台日志:

   2020-07-26 13:13:54.040496+0300 Sport5[10267:1581233] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    "<NSLayoutConstraint:0x2801c7570 V:[UIImageView:0x155dc1dd0]-(0)-|   (active, names: '|':UIView:0x155dc0570 )>",
    "<NSLayoutConstraint:0x2801c75c0 UIView:0x155dc0570.top == UIImageView:0x155dc1dd0.top - 20   (active)>",
    "<NSLayoutConstraint:0x2801c7610 UIView:0x155dc0570.centerY == UIImageView:0x155dc1dd0.centerY   (active)>"
ng constraint 
<NSLayoutConstraint:0x2801c7610 UIView:0x155dc0570.centerY == UIImageView:0x155dc1dd0.centerY   (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2020-07-26 13:13:54.041636+0300 Sport5[10267:1581233] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    "<NSLayoutConstraint:0x2801c77f0 V:[UIImageView:0x155dc27d0]-(0)-|   (active, names: '|':UIView:0x155dc3410 )>",
NSLayoutConstraint:0x2801c7840 UIView:0x155dc3410.top == UIImageView:0x155dc27d0.top - 20   (active)>",
    "<NSLayoutConstraint:0x2801c7890 UIView:0x155dc3410.centerY == UIImageView:0x155dc27d0.centerY   (active)>"
ng constraint 
<NSLayoutConstraint:0x2801c7890 UIView:0x155dc3410.centerY == UIImageView:0x155dc27d0.centerY   (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2020-07-26 13:13:54.042503+0300 Sport5[10267:1581233] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    "<NSLayoutConstraint:0x2801c7a70 V:[UIImageView:0x155dc40c0]-(0)-|   (active, names: '|':UIView:0x155dc3b00 )>",
    "<NSLayoutConstraint:0x2801c7ac0 UIView:0x155dc3b00.top == UIImageView:0x155dc40c0.top - 20   (active)>",
    "<NSLayoutConstraint:0x2801c7b10 UIView:0x155dc3b00.centerY == UIImageView:0x155dc40c0.centerY   (active)>"
Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x2801c7b10 UIView:0x155dc3b00.centerY == UIImageView:0x155dc40c0.centerY   (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2020-07-26 13:13:58.655384+0300 Sport5[10267:1581233] [LayoutConstraints] Window has a view with an ambiguous layout. See "Auto Layout Guide: Ambiguous Layouts" for help debugging. Displaying synopsis from invoking -[UIView _autolayoutTrace] to provide additional detail.
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
2020-07-26 13:13:58.849727+0300 Sport5[10267:1581233] [LayoutConstraints] View has an ambiguous layout. See "Auto Layout Guide: Ambiguous Layouts" for help debugging. Displaying synopsis from invoking -[UIView _autolayoutTrace] to provide additional detail.
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
2020-07-26 13:13:58.855433+0300 Sport5[10267:1581233] [LayoutConstraints] View has an ambiguous layout. See "Auto Layout Guide: Ambiguous Layouts" for help debugging. Displaying synopsis from invoking -[UIView _autolayoutTrace] to provide additional detail.
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
2020-07-26 13:13:58.865918+0300 Sport5[10267:1581233] [LayoutConstraints] View has an ambiguous layout. See "Auto Layout Guide: Ambiguous Layouts" for help debugging. Displaying synopsis from invoking -[UIView _autolayoutTrace] to provide additional detail.
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES ```

布局經理的第一個抱怨非常明顯。 你有一個 x.top = y.top 和另一個 x.top = y.top - 20 的約束。你產生了約束,你應該能夠修復它們。 我沒有再看下去。

事實證明,問題在於 UIStackView 是基於其子視圖的內在內容大小,所以我不得不為大小添加約束而不是使用框架。 之后,我將 UILabel 添加為 UIImageView 的子視圖,並設置了前導尾隨和中心約束,從而解決了問題。 我沒有接受@gnasher729,因為這不是正確的答案,但它確實給了我解決它的提示,為此我感謝他的幫助。

暫無
暫無

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

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