在StackView中设置不同的约束

问题描述 投票:0回答:1

Q. 如何在 stackview、UIKit 中为每个视图设置不同的约束? 我想让屏幕像捕获的那样。

在下面的代码中,结果是好的。但 我有错误无法同时满足约束...

问答之前我学习了StackView。但该屏幕具有相同的限制。就像之前写的那样,我设置了约束,例如

titleLabel.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor, constant: 20)
...

所以,我尝试过失败的原因https://www.wtfautolayout.com/,答案是为每个视图设置0个约束。现在我写了这个问题。感谢您的阅读。

import UIKit

class DetailViewController: UIViewController {
    
    @IBOutlet var centerNavtigationItems: UINavigationItem!

    private let titleLabel: UILabel = {
        let titleLabel = UILabel()
        titleLabel.numberOfLines = 2
        titleLabel.textAlignment = .left
        titleLabel.font = UIFont(name: "Pretendard-SemiBold", size: 24)
        titleLabel.backgroundColor = .yellow
        return titleLabel
    }()
    
    private let dateLabel: UILabel = {
        let view = UILabel()
        view.textAlignment = .right
        view.font = UIFont(name: "Pretendard-Light", size: 16)
        view.textColor = .gray
        return view
    }()
    
    private let scrollView: UIScrollView = {
        let view = UIScrollView()
        return view
    }()
    
    private let imageContainer: UIImageView = {
        let ic = UIImageView()
        return ic
    }()
    
    private let pageController: UIPageControl = {
        let controller = UIPageControl()
        controller.pageIndicatorTintColor = .gray
        controller.currentPageIndicatorTintColor = .darkGray
        return controller
    }()
    
    private let contentTextView: UILabel = {
        let content = UILabel()
        content.numberOfLines = 0
        content.font = UIFont(name: "Pretendard-Regular", size: 18)
        return content
    }()
    
    var fileName: String!
    var id: String!
    var entryNumber: Int!
    var dataSize: Int!
    var entry: Entry!
    var imageNames: [String] = []
    var imageIndex: Int = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // Get contents id and parse file name
        parsingFileName(id: id)
        
        let dateText = String(entry.year) + "." + String(entry.month) + "." + String(entry.day)
        
        centerNavtigationItems.title = dateText
        titleLabel.text = entry.title
        dateLabel.text = dateText
        
        // Add Image to an Array
        // If an image doesn't exist, then set empty array, and make hide UIImageView ... (1)
        if entry.isImage == true {
            
            for e in entry.imageName {
                imageNames.append(String(e + ".jpeg"))
            }
            
            pageController.numberOfPages = imageNames.count
            pageController.currentPage = 0

            print("image name in Array: \(imageNames)")
            imageContainer.image = UIImage(named: imageNames[0])
            
            pageController.addTarget(self, action: #selector(action(sender: )), for: .touchUpInside)
        }
    
        // Set Swipe Gesture for the image container
        let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(DetailViewController.reponderToSwipeGesture(_:)))
        swipeRight.direction = UISwipeGestureRecognizer.Direction.right
        self.imageContainer.addGestureRecognizer(swipeRight)
        
        let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(DetailViewController.reponderToSwipeGesture(_:)))
        swipeLeft.direction = UISwipeGestureRecognizer.Direction.left
        self.imageContainer.addGestureRecognizer(swipeLeft)
        
        // Set textView Contents
        contentTextView.text = entry.article
        
        // stackView Setting
        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.spacing = 8
        
        // Arrange subviews to Stack View
        [titleLabel, dateLabel, imageContainer, contentTextView].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
            stackView.addArrangedSubview(v)
        }
        
        // If image doesn't exist (1) Set the image container hidden
        if entry.isImage == true {
            imageContainer.heightAnchor.constraint(equalToConstant: self.view.frame.width).isActive = true
        } else {
            imageContainer.isHidden = true
        }
        
        // Set stakcView and scrollView
        stackView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(stackView)
        view.addSubview(scrollView)
        
        // Set constraint
        let g = view.safeAreaLayoutGuide
        let cg = scrollView.contentLayoutGuide
        let fg = scrollView.frameLayoutGuide
        
        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0),
            scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0),
            scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -0),
            scrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -0),
            
            stackView.topAnchor.constraint(equalTo: cg.topAnchor, constant: 0.0),
            stackView.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 0.0),
            stackView.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -0.0),
            stackView.bottomAnchor.constraint(equalTo: cg.bottomAnchor, constant: -0.0),
            stackView.widthAnchor.constraint(equalTo: fg.widthAnchor, constant: -0),
            
            // set detail components constraint
            titleLabel.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -20),
            titleLabel.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 20),

            dateLabel.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -20),
            dateLabel.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 20),
            
            imageContainer.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 0),
            imageContainer.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: 0),
            
            contentTextView.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 20),
            contentTextView.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -20),
        ])
    }
    
}

错误

Unknown class detail in Interface Builder file.
Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (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:0x6000021406e0 UILabel:0x103c1f3a0.leading == _UIScrollViewLayoutGuide:0x600003b0ea00'UIScrollView-contentLayoutGuide'.leading + 20   (active)>",
    "<NSLayoutConstraint:0x600002140050 UIImageView:0x103c183d0.leading == _UIScrollViewLayoutGuide:0x600003b0ea00'UIScrollView-contentLayoutGuide'.leading   (active)>",
    "<NSLayoutConstraint:0x60000213b2f0 'UISV-alignment' UILabel:0x103c1f3a0.leading == UIImageView:0x103c183d0.leading   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000213b2f0 'UISV-alignment' UILabel:0x103c1f3a0.leading == UIImageView:0x103c183d0.leading   (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.
Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (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:0x600002142800 UILabel:0x103c1f3a0.trailing == _UIScrollViewLayoutGuide:0x600003b0ea00'UIScrollView-contentLayoutGuide'.trailing - 20   (active)>",
    "<NSLayoutConstraint:0x600002140820 UIImageView:0x103c183d0.trailing == _UIScrollViewLayoutGuide:0x600003b0ea00'UIScrollView-contentLayoutGuide'.trailing   (active)>",
    "<NSLayoutConstraint:0x60000213b250 'UISV-alignment' UILabel:0x103c1f3a0.trailing == UIImageView:0x103c183d0.trailing   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000213b250 'UISV-alignment' UILabel:0x103c1f3a0.trailing == UIImageView:0x103c183d0.trailing   (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.
Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (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:0x600002140aa0 UIStackView:0x103c27b90.leading == _UIScrollViewLayoutGuide:0x600003b0ea00'UIScrollView-contentLayoutGuide'.leading   (active)>",
    "<NSLayoutConstraint:0x6000021406e0 UILabel:0x103c1f3a0.leading == _UIScrollViewLayoutGuide:0x600003b0ea00'UIScrollView-contentLayoutGuide'.leading + 20   (active)>",
    "<NSLayoutConstraint:0x60000213b1b0 'UISV-canvas-connection' UIStackView:0x103c27b90.leading == UILabel:0x103c1f3a0.leading   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000213b1b0 'UISV-canvas-connection' UIStackView:0x103c27b90.leading == UILabel:0x103c1f3a0.leading   (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.
Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (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:0x6000021414a0 UIStackView:0x103c27b90.trailing == _UIScrollViewLayoutGuide:0x600003b0ea00'UIScrollView-contentLayoutGuide'.trailing   (active)>",
    "<NSLayoutConstraint:0x600002142800 UILabel:0x103c1f3a0.trailing == _UIScrollViewLayoutGuide:0x600003b0ea00'UIScrollView-contentLayoutGuide'.trailing - 20   (active)>",
    "<NSLayoutConstraint:0x60000213b200 'UISV-canvas-connection' H:[UILabel:0x103c1f3a0]-(0)-|   (active, names: '|':UIStackView:0x103c27b90 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000213b200 'UISV-canvas-connection' H:[UILabel:0x103c1f3a0]-(0)-|   (active, names: '|':UIStackView:0x103c27b90 )>

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.
ios swift uikit constraints
1个回答
0
投票

我认为您的主要问题是您在堆栈视图中对视图设置的约束以及您未能完全配置堆栈视图。

  1. 删除以下限制:

    titleLabel.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -20),
    titleLabel.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 20),
    dateLabel.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -20),
    dateLabel.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 20),
    imageContainer.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 0),
    imageContainer.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: 0),
    contentTextView.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 20),
    contentTextView.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -20),
    

    以下更改将确保堆栈视图的视图填充堆栈视图的宽度。

  2. 通过设置

    distribution
    alignment
    属性来完全设置堆栈视图。您可能需要在设置
    axis
    后添加以下两行:

    stackView.distribution = .equalSpacing // Use each view's intrinsic height as-is when possible
    stackView.alignment = .fill // Make each view's width the same as the width of the stack view
    
  3. 您应该更改图像视图的高度限制。替换:

    imageContainer.heightAnchor.constraint(equalToConstant: self.view.frame.width).isActive = true
    

    与:

    imageContainer.heightAnchor.constraint(equalTo: imageContainer.widthAnchor).isActive = true
    

    这将使图像视图的高度与其宽度相同,这就是我认为您正在尝试做的事情(使其成为正方形)。图像视图的宽度将来自于填充堆栈视图的宽度。

© www.soinside.com 2019 - 2024. All rights reserved.