SwiftUI 中的内容拥抱优先行为 [英] Content hugging priority behaviour in SwiftUI

查看:27
本文介绍了SwiftUI 中的内容拥抱优先行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个由单元格组成的列表,每个单元格包含一个图像和一列文本,我希望以特定的方式对其进行布局.左侧图像,占宽度的四分之一.文本的剩余空间,左对齐.

I have a List made of cells, each containing an image, and a column of text, which I wish laid out in a specific way. Image on the left, taking up a quarter of the width. The rest of the space given to the text, which is left-aligned.

这是我得到的代码:

struct TestCell: View {
    let model: ModelStruct

    var body: some View {
        HStack {
            Image("flag")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: UIScreen.main.bounds.size.width * 0.25)
            VStack(alignment: .leading, spacing: 5) {
                Text("Country: Moldova")
                Text("Capital: Chișinău")
                Text("Currency: Leu")
            }
            .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
        }
    }
}

struct TestCell_Previews: PreviewProvider {
    static var previews: some View {
        TestCell()
            .previewLayout(.sizeThatFits)
            .previewDevice("iPhone 11")
    }
}

这里有两个例子:

如您所见,整个单元格的高度因图像的纵横比而异.

As you can see, the height of the whole cell varies based on the aspect ratio of the image.

100 万美元的问题 - 我们如何让单元格高度紧贴文本(如第二张图像中)而不变化,而是在分配的内部以 scaleAspectFit 方式缩小图像矩形

$1M question - How can we make the cell height hug the text (like in the second image) and not vary, but rather shrink the image in a scaleAspectFit manner inside the allocated rectangle

注意!

  1. 文本的高度可能会有所不同,因此无需进行硬编码.
  2. 无法使其与 PreferenceKey 一起使用,因为单元格将成为列表的一部分,并且我试图围绕单元格重用和 onPreferenceChange 了解一些特殊行为 当 2 个连续的单元格具有相同的高度时不会被调用.要展示所有这些组合行为,请确保您的模型在测试时因单元格而异.
  1. The text's height can vary, so no hardcoding.
  2. Couldn't make it work with PreferenceKeys, as the cells will be part of a List, and there's some peculiar behaviour I'm trying to grasp around cell reusage, and onPreferenceChange not being called when 2 consecutive cells have the same height. To exhibit all this combined behaviour, make sure your model varies between cells when you test it.

推荐答案

这是一个可能的解决方案,但是它使用 VStack 的背景属性中的 GeometryReader 来检测它们的高度.然后将该高度应用于图像.我使用了 this 解决方案中的 SizePreferenceKey.

Here is a possible solution, however it uses GeometryReader inside the background property of the VStack, to detect their height. That height is being applied to the Image then. I used SizePreferenceKey from this solution.

struct SizePreferenceKey: PreferenceKey {
    typealias Value = CGSize
    static var defaultValue: Value = .zero

    static func reduce(value _: inout Value, nextValue: () -> Value) {
        _ = nextValue()
    }
}

struct ContentView6: View {

    @State var childSize: CGSize = .zero
    
    var body: some View {
        HStack {
            Image("image1")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: UIScreen.main.bounds.size.width * 0.25, height: self.childSize.height)
            VStack(alignment: .leading, spacing: 5) {
                Text("Country: Moldova")
                Text("Capital: Chișinău")
                Text("Currency: Leu")
            }
            .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
            .background(
                  GeometryReader { proxy in
                    Color.clear.preference(key: SizePreferenceKey.self, value: proxy.size)
                   }
                 )
        }
        .onPreferenceChange(SizePreferenceKey.self) { preferences in
          self.childSize = preferences
        }
        .border(Color.yellow)

    }
      

}

看起来像这样..当然,您可以为图像应用不同的纵横比.

Will look like this.. you can apply different aspect ratios for the Image of course.

这篇关于SwiftUI 中的内容拥抱优先行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆