简体   繁体   English

如何以 UIImageView 作为其子级来制作水平 UIStackView 换行高度内容?

[英]How to make horizontal UIStackView wrap height content with UIImageView as its children?

I have the following horizontal UIStackView我有以下水平UIStackView

  1. Yellow background黄色背景
  2. Leading, top and trailing same as safe area前导,顶部和尾随与安全区域相同
  3. Alignment = Top Alignment = 顶部
  4. Distribution = Fill Proportionally分配 = 按比例填充

UILabel as children小时候的UILabel

If I add UILabel as its children, it will automatically wrap height content as below如果我将UILabel添加为其子项,它将自动包装高度内容,如下所示

在此处输入图像描述


UIImage as children UIImage 作为孩子

I replace UILabel with 3 identical UIImageView .我用 3 个相同UIImageView替换UILabel

Every UIImageView has the following properties每个UIImageView具有以下属性

  1. Content mode = Aspect Fit内容模式 = Aspect Fit

It looks as following它看起来如下

在此处输入图像描述

I was wondering, how can I make the horizontal UIStackView wrap to its height content?我想知道,如何使水平UIStackView包装到它的高度内容?

I expect the UIStackView 's will wrap the UIImageView 's content height.我希望UIStackView将包装UIImageView的内容高度。 As an outcome, we will not observe any yellow background of UIStackView .结果,我们不会观察到UIStackView的任何黄色背景。

May I know, how can I achieve so?我可以知道,我怎样才能做到这一点?

So far, I have tried to play around with到目前为止,我试图玩弄

  1. Content hugging priority of both UIStackView and UIImageView UIStackView 和 UIImageView 的内容拥抱优先级
  2. Content compression resistance priority for both UIStackView and UIImageView UIStackView 和 UIImageView 的内容压缩阻力优先级

Still not able to achieve my desired outcome.仍然无法达到我想要的结果。


The following is the original image source, which is 606x404以下是原图源,为606x404

在此处输入图像描述

You cannot get this result with only Storyboard setup -- you will need some code.仅使用 Storyboard 设置无法获得此结果 - 您将需要一些代码。

Based on your image showing your desired output, you want each "row" to:根据显示所需 output 的图像,您希望每个“行”:

  • have 3 images有 3 张图片
  • show them at original aspect-ratio以原始纵横比显示它们
  • small spacing between images (such as 4-pts)图像之间的小间距(例如 4-pts)
  • fit so the widths and heights maintain the ratios适合所以宽度和高度保持比率

First comment - forget Distribution = Fill Proportionally on the stack views.第一条评论 - 忘记Distribution = Fill Proportionally

For this layout, the stack view should be:对于此布局,堆栈视图应为:

  • Axis: Horizontal
  • Alignment: Fill
  • Distribution: Fill
  • Spacing: 4

So, what we need to do is constrain each imageView's aspect ratio based on its image's aspect ratio (height / width).所以,我们需要做的是根据图像的纵横比(高度/宽度)来约束每个 imageView 的纵横比。

Here is a full example... it uses these 6 images:这是一个完整的示例……它使用了这 6 个图像:

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

We'll also embed the horizontal stack view(s) in a vertical stack view, using the same settings (expect Axis: Vertical ).我们还将使用相同的设置(期望Axis: Vertical )将水平堆栈视图嵌入到垂直堆栈视图中。

class AdjustStackViewController: UIViewController {
    
    var vStack = UIStackView()
    
    var picNames: [String] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // six images, named "p1" - "p6"
        for i in 1...6 {
            picNames.append("p\(i)")
        }
        
        // vertical stack view
        vStack.axis = .vertical
        vStack.spacing = 4
        
        // use auto-layout
        vStack.translatesAutoresizingMaskIntoConstraints = false
        
        // add it to the view
        view.addSubview(vStack)
        
        // respect safe-area
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            // constrain vStack
            //  Top + 20
            //  Leading and Trailing 0
            vStack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            vStack.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            vStack.trailingAnchor.constraint(equalTo: g.trailingAnchor),
        ])
        
        fillStacks()
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // re-fill images in new (shuffled) order
        fillStacks()
    }
    
    func fillStacks() -> Void {
        
        // remove existing horizontal stack views (if needed)
        vStack.arrangedSubviews.forEach { v in
            v.removeFromSuperview()
        }
        
        let shuffledImages = picNames.shuffled()

        // two horizontal stack views each with 3 images
        var picNum: Int = 0
        for _ in 1...2 {
            let hStack = UIStackView()
            hStack.spacing = 4
            vStack.addArrangedSubview(hStack)
            for _ in 1...3 {
                // make sure we can load the images
                guard let img = UIImage(named: shuffledImages[picNum]) else {
                    fatalError("Could not load images!")
                }
                // create Image View
                let imgView = UIImageView()
                // set the image
                imgView.image = img
                // proportional constraint based on image dimensions
                imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor, multiplier: img.size.height / img.size.width).isActive = true
                // add to hStack
                hStack.addArrangedSubview(imgView)
                // increment pic number
                picNum += 1
            }
        }

    }
    
}

Here's how it looks:这是它的外观:

在此处输入图像描述

When you run this, each time you tap the view it will shuffle the order of the images, so you can see how the layout adapts.当你运行它时,每次你点击视图时,它都会打乱图像的顺序,这样你就可以看到布局是如何适应的。

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

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