Поведение приоритета захвата контента в SwiftUI - PullRequest
2 голосов
/ 08 июля 2020

У меня есть Список , состоящий из ячеек, каждая из которых содержит изображение, и столбца текста, который я sh выложил определенным c способом. Изображение слева, занимающее четверть ширины. Остальное пространство отведено под текст, который выровнен по левому краю.

Вот полученный мной код:

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")
    }
}

И вот 2 примера:

image image

Как видите, высота всей ячейки варьируется в зависимости от соотношения сторон изображения.

1 млн долларов на вопрос - Как сделать так, чтобы высота ячейки охватывала текст ( как на втором изображении) и не изменять, а скорее сжимать изображение в виде scaleAspectFit внутри выделенного прямоугольника

Примечание!

  1. высота текста может меняться, поэтому без жесткого кодирования.
  2. Не удалось заставить его работать с PreferenceKey s, так как ячейки будут частью списка, и есть какое-то странное поведение, которое я пытаюсь gr asp вокруг повторного использования ячеек и onPreferenceChange не вызывается, когда 2 последовательные ячейки имеют одинаковую высоту. Чтобы продемонстрировать все это комбинированное поведение, убедитесь, что ваша модель различается между ячейками при ее тестировании.

1 Ответ

1 голос
/ 08 июля 2020

Вот возможное решение, однако оно использует GeometryReader внутри свойства background VStack для определения их высоты. Затем эта высота применяется к изображению. Я использовал SizePreferenceKey из это решение.

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)

    }
      

}

Будет выглядеть так ... Конечно, вы можете применить крысу с другим аспектом ios для изображения.

image
...