Почему добавление HStack внутри VStack приводит к сбоям в расчетах размера ZStack вокруг текстовых элементов?

Я хочу создать пузырьковый вид с различными фрагментами текста на фоне прямоугольника со скругленными углами, размер которого соответствует размеру текста. Я пришел к этому:

          var body: some View {
        HStack {
            Spacer()
            ZStack(alignment: .trailing) {
                Color.blue
                VStack{
                    Text(message.content)
                        .padding(.all, .oneUnit)
                        .multilineTextAlignment(.trailing)
                }
            }
            .clipShape(RoundedRectangle(cornerRadius: 12))
        }
    }

Когда это повторяется сForEachи некоторый текст, переданный как сообщение, содержание почти правильное, но фон должен быть достаточно большим, чтобы покрыть текст, создавая пузырь:

С использованием.layoutPriorityисправляет это, код становится:

          var body: some View {
        HStack {
            Spacer()
            ZStack(alignment: .trailing) {
                Color.blue
                VStack{
                    Text(message.content)
                        .padding(.all, .oneUnit)
                        .multilineTextAlignment(.trailing)
                }
                .layoutPriority(1)
            }
            .clipShape(RoundedRectangle(cornerRadius: 12))
        }
    }

Таким образом, размер - это размер, необходимый для размещения текста. Большой! Теперь, чтобы поместить все необходимые фрагменты текста вVStack. Добавим еще одинText:

          var body: some View {
        HStack {
            Spacer()
            ZStack(alignment: .trailing) {
                Color.blue
                VStack{
                    Text(message.content)
                        .padding(.all, .oneUnit)
                        .multilineTextAlignment(.trailing)
                    Text("Out damned spot!")
                }
                .layoutPriority(1)
            }
            .clipShape(RoundedRectangle(cornerRadius: 12))
        }
    }

Текстовый дисплей внизу, размер все еще правильный.

Но этот последний фрагмент текста должен быть выровнен по правому краю. Итак, код:

          var body: some View {
        HStack {
            Spacer()
            ZStack(alignment: .trailing) {
                Color.blue
                VStack{
                    Text(message.content)
                        .padding(.all, .oneUnit)
                        .multilineTextAlignment(.trailing)
                    HStack {
                        Spacer()
                        Text("Out damned spot!")
                    }
                }
                .layoutPriority(1)
            }
            .clipShape(RoundedRectangle(cornerRadius: 12))
        }
    }

А то все ломается. Кто-нибудь может сказать, почемуHStackломаетZStackразмер?

1 ответ

@SwissMark прав, причина вашей проблемы в том, чтоSpacer()жадный, он занимает все оставшееся место. Сделайте ваши пузыри максимально возможным размером. Но только делаяVStackвыравнивание.trailingне делает трюк.

Проблемы:

  1. Ваш фон установлен вZStack
  2. layoutPriority здесь не имеет никакого смысла

Вот решение:

      import SwiftUI

struct ContentView: View {
    
    var messages = [
        "I heard the owl scream and the crickets cry.",
        "Out damned spot!",
        "Did not you speak?",
        "Out damned spot!",
        "When?",
        "Out damned spot!",
        "Now.",
        "Out damned spot!"
    ]
    
    var body: some View {
        HStack {
            Spacer()
            ZStack(alignment: .trailing) {
                VStack(alignment: .trailing) {
                    VStack(alignment: .trailing) {
                        Text(messages[0])
                            .padding(.all, 4)
                            .multilineTextAlignment(.trailing)
                        Text(messages[1])
                            .padding([.bottom, .trailing], 4)
                    }
                    .padding(4)
                    .background(Color.blue)
                    .clipShape(RoundedRectangle(cornerRadius: 12))
                    
                    VStack(alignment: .trailing) {
                        Text(messages[2])
                            .padding(.all, 4)
                            .multilineTextAlignment(.trailing)
                        Text(messages[3])
                            .padding([.bottom, .trailing], 4)
                    }
                    .padding(4)
                    .background(Color.blue)
                    .clipShape(RoundedRectangle(cornerRadius: 12))
                    
                    VStack(alignment: .trailing) {
                        Text(messages[4])
                            .padding(.all, 4)
                            .multilineTextAlignment(.trailing)
                        Text(messages[5])
                            .padding([.bottom, .trailing], 4)
                    }
                    .padding(4)
                    .background(Color.blue)
                    .clipShape(RoundedRectangle(cornerRadius: 12))
                    
                    VStack(alignment: .trailing) {
                        Text(messages[6])
                            .padding(.all, 4)
                            .multilineTextAlignment(.trailing)
                        Text(messages[7])
                            .padding([.bottom, .trailing], 4)
                    }
                    .padding(4)
                    .background(Color.blue)
                    .clipShape(RoundedRectangle(cornerRadius: 12))
                }
            }
        }
    }
}

Окончательное изображение:

Измените отступы и пробелы по своему усмотрению.

Другие вопросы по тегам