繁体   English   中英

Swift:UIView 未调整大小以适合内容

[英]Swift: UIView not resizing to fit content

我正在构建一个应用程序,其中有一个评论列表。 它们看起来像下面的截图审查 出于某种原因,我无法正确调整 UIView(从顶部浅灰色线到底部的灰色框)的大小。 其中的白色文本(实际评论)超过 1 行,不应被截断,仅当达到最多 5 行时。 问题是,当我没有为您在左侧看到的用户图像设置宽度和高度限制时,它会起作用。 删除这些将使视图正确调整大小,但它会完全扭曲图像。 图像顶部和底部锚点似乎粘附在其水平堆栈视图中的锚点上,它们再次粘附在 UIView 的顶部和底部锚点上并带有常量,正如它应该的那样。 但我没有说 UIView 应该始终具有图像的大小。 我不明白为什么它不会 go 比图像大。

这是我的带有约束的结构的屏幕截图,希望它足够清楚: 结构

                NSLayoutConstraint.activate([
                //Main horizontal stackview (one Rating is the name of the UIView)
                hStack.leadingAnchor.constraint(equalTo: oneRating.leadingAnchor, constant: 23),
                hStack.trailingAnchor.constraint(equalTo: oneRating.trailingAnchor, constant: -18),
                hStack.topAnchor.constraint(equalTo: oneRating.topAnchor, constant: 15),
                hStack.bottomAnchor.constraint(equalTo: oneRating.bottomAnchor, constant: -13),
                
                reviewerImage.heightAnchor.constraint(equalToConstant: 80),
                reviewerImage.widthAnchor.constraint(equalToConstant: 80),
                                    
                //Limit the size of the Review Text to make sure its always at the same spot
                v2Stack.widthAnchor.constraint(equalToConstant: 220.0),
            ])
            
            //Verified checkmark constraints
            if isUserVerified == true {
                reviewerVerified.bottomAnchor.constraint(equalTo: reviewerImage.bottomAnchor).isActive = true
                reviewerVerified.trailingAnchor.constraint(equalTo: reviewerImage.trailingAnchor, constant: -2).isActive = true
            }

我知道这样很难提供帮助,但我已经尝试解决这个问题几天了,无论我做什么,我都无法让它发挥作用。

编辑:根据要求,这是我必须将 ImageView 添加到我的 UIView() 的代码。

                //Add Image
            let reviewerImage = UIImageView()
            reviewerImage.contentMode = .scaleAspectFill
            reviewerImage.layer.cornerRadius = 40 //= 1/2 of width, because we hard coded the size
            reviewerImage.image = UIImage(named: "person-icon") //Placeholder. Download image here
            

reviewerImage.translatesAutoresizingMaskIntoConstraints = false VStack1.addArrangedSubview(reviewerImage)

需要添加更多的尺寸限制,但是......

“技巧”是将您的“审阅者图像视图”嵌入清晰的“容器”视图中。 然后将图像视图限制在该容器的顶部。

这是一些接近您的布局的示例代码:

class JanView: UIView {
    
    let reviewerImageView: UIImageView = {
        let v = UIImageView()
        return v
    }()
    let starImageView: UIImageView = {
        let v = UIImageView()
        return v
    }()
    let chevronImageView: UIImageView = {
        let v = UIImageView()
        return v
    }()
    let nameLabel: UILabel = {
        let v = UILabel()
        return v
    }()
    let locLabel: UILabel = {
        let v = UILabel()
        return v
    }()
    let reviewTextLabel: UILabel = {
        let v = UILabel()
        v.numberOfLines = 5
        return v
    }()
    let publishedLabel: UILabel = {
        let v = UILabel()
        return v
    }()
    let starValueLabel: UILabel = {
        let v = UILabel()
        v.textAlignment = .center
        return v
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        
        backgroundColor = .darkGray
        
        let outerHStack: UIStackView = {
            let v = UIStackView()
            v.spacing = 10
            return v
        }()
        let labelsVStack: UIStackView = {
            let v = UIStackView()
            v.axis = .vertical
            v.spacing = 0
            return v
        }()
        let starsAndChevronVStack: UIStackView = {
            let v = UIStackView()
            v.axis = .vertical
            v.spacing = 0
            return v
        }()
        let starsHStack: UIStackView = {
            let v = UIStackView()
            v.spacing = 0
            v.alignment = .center
            return v
        }()
        
        // review image container
        let reviewerImageContainer: UIView = {
            let v = UIView()
            return v
        }()
        
        [nameLabel, reviewTextLabel].forEach { v in
            v.textColor = .white
        }
        [locLabel, publishedLabel].forEach { v in
            v.textColor = .lightGray
        }
        starValueLabel.textColor = .systemYellow
        
        outerHStack.translatesAutoresizingMaskIntoConstraints = false
        
        addSubview(outerHStack)
        
        [nameLabel, locLabel, reviewTextLabel, publishedLabel].forEach { v in
            labelsVStack.addArrangedSubview(v)
        }
        [starValueLabel, starImageView].forEach { v in
            starsHStack.addArrangedSubview(v)
        }
        [starsHStack, chevronImageView].forEach { v in
            starsAndChevronVStack.addArrangedSubview(v)
        }
        [reviewerImageContainer, labelsVStack, starsAndChevronVStack].forEach { v in
            outerHStack.addArrangedSubview(v)
        }
        
        // add reviewer image view to container
        reviewerImageContainer.addSubview(reviewerImageView)
        reviewerImageView.translatesAutoresizingMaskIntoConstraints = false
        
        // specific properties
        reviewerImageView.contentMode = .scaleAspectFill
        reviewerImageView.layer.cornerRadius = 40
        reviewerImageView.layer.masksToBounds = true
        
        let cfg = UIImage.SymbolConfiguration(pointSize: 12.0, weight: .bold)
        if let img = UIImage(systemName: "star.fill", withConfiguration: cfg) {
            starImageView.image = img
        }
        starImageView.tintColor = .systemYellow
        starImageView.contentMode = .center
        starValueLabel.text = "4"
        
        if let img = UIImage(systemName: "chevron.right", withConfiguration: cfg) {
            chevronImageView.image = img
        }
        chevronImageView.tintColor = .lightGray
        chevronImageView.contentMode = .center
        
        nameLabel.text = "Name Here"
        locLabel.text = "Location Here"
        reviewTextLabel.text = "Review Text Here"
        publishedLabel.text = "Published Info Here"
        
        let g = self
        
        // to get the 2nd vertical stack view to fit (horizontally) to its content
        let sacWidth = starsAndChevronVStack.widthAnchor.constraint(equalToConstant: 10.0)
        sacWidth.priority = .defaultHigh
        
        let vPadding: CGFloat = 12
        let hPadding: CGFloat = 10
        
        NSLayoutConstraint.activate([
            
            outerHStack.topAnchor.constraint(equalTo: g.topAnchor, constant: vPadding),
            outerHStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: hPadding),
            outerHStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -hPadding),
            outerHStack.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -vPadding),
            
            reviewerImageView.widthAnchor.constraint(equalToConstant: 80.0),
            reviewerImageView.heightAnchor.constraint(equalTo: reviewerImageView.widthAnchor),
            
            // align the reviewer image view with the top of the container view
            reviewerImageView.topAnchor.constraint(equalTo: reviewerImageContainer.topAnchor),
            reviewerImageView.leadingAnchor.constraint(equalTo: reviewerImageContainer.leadingAnchor),
            reviewerImageView.trailingAnchor.constraint(equalTo: reviewerImageContainer.trailingAnchor),

            // give the stars value label a width, so it doesn't vary by text
            //  "5" is wider than "1" (or it may be "" ?)
            starValueLabel.widthAnchor.constraint(equalToConstant: 16.0),
            
            // make the star image view square
            starImageView.widthAnchor.constraint(equalTo: starImageView.heightAnchor),
            
            // make the stars HStack height equal to the stars label height
            starsHStack.heightAnchor.constraint(equalTo: starValueLabel.heightAnchor),
            
            sacWidth,
            
        ])
        
    }
    
}

和一个例子 controller:

class ReviewVC: UIViewController {
    let scrollView: UIScrollView = {
        let v = UIScrollView()
        return v
    }()
    let reviewsStack: UIStackView = {
        let v = UIStackView()
        v.axis = .vertical
        v.spacing = 0
        return v
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        [reviewsStack, scrollView].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
        }
        scrollView.addSubview(reviewsStack)
        view.addSubview(scrollView)
        
        let g = view.safeAreaLayoutGuide
        let contentG = scrollView.contentLayoutGuide
        let frameG = scrollView.frameLayoutGuide
        
        NSLayoutConstraint.activate([
            
            scrollView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            scrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
            
            reviewsStack.topAnchor.constraint(equalTo: contentG.topAnchor, constant: 0.0),
            reviewsStack.leadingAnchor.constraint(equalTo: contentG.leadingAnchor, constant: 0.0),
            reviewsStack.trailingAnchor.constraint(equalTo: contentG.trailingAnchor, constant: 0.0),
            reviewsStack.bottomAnchor.constraint(equalTo: contentG.bottomAnchor, constant: 0.0),

            reviewsStack.widthAnchor.constraint(equalTo: frameG.widthAnchor, constant: 0.0),
            
        ])
        
        let sampleLocs: [String] = [
            "Koblenz, Germany",
            "Westerwald, Germany",
            "Bonn, Germany",
            "Saarbrüken, Germany",
        ]
        let sampleRevs: [String] = [
            "For some reason, I am failing to make the UIView (Gray box from the top light gray line to the bottom one) resize correctly.",
            "A Single Line",
            "The white text inside it (Actual review) is longer than 1 line and should not get cut off, only when reaching a maximum of say 5 lines.",
            "The thing is, it works when I don't set width and height constraints for the user image you see on the left side. Removing those will make the view resize correctly, but it will completely distort the image.",
            "Another Single Line",
            "The image top and botton anchors seem to be glued to the anchors in its horizontal stackview, which again are stuck to the UIView's top and botton anchors with constants, as it should.",
        ]
        let sampleStars: [String] = [
            "5", "4", "3", "2", "1",
        ]
        for i in 0..<sampleRevs.count {
            let v = JanView()
            v.nameLabel.text = "Clara R."
            v.locLabel.text = sampleLocs[i % sampleLocs.count]
            v.reviewTextLabel.text = sampleRevs[i]
            v.publishedLabel.text = "Published less than 24h ago"
            v.starValueLabel.text = sampleStars[i % sampleStars.count]
            if let img = UIImage(named: "prof") {
                v.reviewerImageView.image = img
            }
            reviewsStack.addArrangedSubview(v)
            let sepView = UIView()
            sepView.backgroundColor = .lightGray
            sepView.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
            reviewsStack.addArrangedSubview(sepView)
        }
        
    }
}

这是它最终的样子:

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM