SwiftUI отличается выравнивание текста в VStack - PullRequest
0 голосов
/ 30 января 2020

У меня есть пример чата, с 3 текстами, именем, текстом и часом. Я хотел бы выровнять первые два текста по левому и другому по правому.

var body: some View {
            HStack {
                if self.cloudPosition == .dx {Spacer(minLength: 20)}
                VStack (alignment: .leading) {
                    Text("\(self.text.name)")
                        .font(.system(size: 15))
                        .foregroundColor(Self.getColor(index: self.text.colorIndex))
                        .padding(EdgeInsets(top: 3, leading: 15, bottom: 3, trailing: 10))
                    Text("\(self.text.text)")
                        .font(.system(size: 15))
                        .padding(EdgeInsets(top: 0, leading: 8, bottom: 0, trailing: 8))
                    HStack {
                        Spacer() //I remove this in example 3 
                        Text("\(self.text.date, formatter: Self.timeFormat) ")
                            .font(.system(size: 9))
                            .foregroundColor(.gray)
                            .padding(3)
                    }
                }
                .background(self.cloudColor)
                .cornerRadius(10)
                .padding(10)
                if self.cloudPosition == .sx {Spacer(minLength: 20)}
            }
    }

Перечисление:

enum CloudPosition {
    case dx,sx
}

, если текст является лог, это нормально. ПРИМЕР 1 :

enter image description here

но если коротко, ПРИМЕР 2:

enter image description here

если я удаляю Spacer () ПРИМЕР 3, с чатом все в порядке, но час не справа:

enter image description here

Есть идеи? спасибо

1 Ответ

2 голосов
/ 31 января 2020

Одна из возможностей ... проверить это с игровой площадкой

Объяснять особо нечего, «трюк» делается с правильной комбинацией различных стеков, выравниванием, .fixedSize(horizontal:, vertical:), Color.clear.frame(height:0) заменой Spacer(). Все вместе делает это "автоматическое c" расширение представления сообщения, основанное на тексте сообщения.

import SwiftUI
import PlaygroundSupport

struct ContentView: View {

    var body: some View {

        VStack {

            HStack {
                Spacer()
                HStack {
                    VStack (alignment: .leading) {
                        Text("Lorem ipsum")
                            .font(.title)
                            .fixedSize()

                        Text("""
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
                        """)
                            .font(.system(size: 15))
                            .fixedSize(horizontal: false, vertical: true)

                        HStack {
                            Color.clear.frame(height: 0)
                            Text("22:13").fixedSize()
                        }
                    }
                    .padding()
                    .background(Color.yellow)
                    .cornerRadius(10)
                    .padding()

                }
                .scaledToFit()
            }
            .border(Color.red)

            HStack {
                Spacer()
                HStack {
                    VStack (alignment: .leading) {
                        Text("Lorem ipsum")
                            .font(.title)
                            .fixedSize()

                        Text("?")
                            .font(.system(size: 15))
                            .fixedSize(horizontal: false, vertical: true)

                        HStack {
                            Color.clear.frame(height: 0)
                            Text("22:13").fixedSize()
                        }
                    }
                    .padding()
                    .background(Color.yellow)
                    .cornerRadius(10)
                    .padding()

                }
                .scaledToFit()
            }
            .border(Color.red)

            HStack {
                Spacer()
                HStack {
                    VStack (alignment: .leading) {
                        Text("?")
                            .font(.title)
                            .fixedSize()

                        Text("Lorem ipsum")
                            .font(.system(size: 15))
                            .fixedSize(horizontal: false, vertical: true)

                        HStack {
                            Color.clear.frame(height: 0)
                            Text("22:13").fixedSize()
                        }
                    }
                    .padding()
                    .background(Color.yellow)
                    .cornerRadius(10)
                    .padding()

                }
                .scaledToFit()
            }
            .border(Color.red)

            Spacer()
        }
    }
}

PlaygroundPage.current.setLiveView(ContentView())

РЕЗУЛЬТАТ:

enter image description here

Один и тот же код повторяется 3 раза, просто потому, что я ленивый: -)

Наконец, вы можете использовать что-то вроде

struct Message<Header: View, Footer: View>: View {
    let header: Header
    let footer: Footer
    let message: String
    let color: Color

    var body: some View {
        HStack {
            Spacer()
            HStack {
                VStack (alignment: .leading) {
                    header.fixedSize()

                    Text(message)
                        .fixedSize(horizontal: false, vertical: true)

                    HStack {
                        color.frame(height: 0)
                        footer.fixedSize()
                    }
                }
                .padding()
                .background(color)
                .cornerRadius(10)
                .padding()

            }
            .scaledToFit()
        }
    }
}

или , используя @ViewBulder для верхнего и нижнего колонтитула

struct MessageBuilder<Header, Footer>: View where Header: View, Footer: View {

    let header: () -> Header
    let footer: () -> Footer
    let message: String
    let color: Color

    init(@ViewBuilder header: @escaping () -> Header, @ViewBuilder footer: @escaping () -> Footer, message: String, color: Color) {
        self.header = header
        self.footer = footer
        self.message = message
        self.color = color
    }

    var body: some View {
        HStack {
            Spacer()
            HStack {
                VStack (alignment: .leading) {
                    header().fixedSize()

                    Text(message)
                        .fixedSize(horizontal: false, vertical: true)

                    HStack {
                        color.frame(height: 0)
                        footer().fixedSize()
                    }
                }
                .padding()
                .background(color)
                .cornerRadius(10)
                .padding()

            }
            .scaledToFit()
        }
    }

}

и затем используйте его в своем коде

struct ContentView: View {

    var body: some View {

        VStack {

            Message(header: Text("Header").font(.title), footer: Text("22:13"), message: "long or short message text", color: Color.blue.opacity(0.2))

            MessageBuilder(header: {
                HStack {
                    Image(systemName: "square.and.arrow.down")
                    Text("Fred")
                }
            }, footer: {
                Image(systemName: "clock")
            }, message: "message text", color: Color.gray.opacity(0.2))

            Spacer()
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...