SwiftUI中VStack中文字的不同对齐方式

12

我有一个聊天示例,其中包含三个文本:名称、文本和时间。 我希望将前两个文本左对齐,将最后一个文本右对齐。

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
}

如果文本很长,就没问题。例如:

在这里输入图片描述

但如果很短,就会出现问题。例如:

在这里输入图片描述

如果我去掉 Spacer()(例 3),聊天是 ok 的,但小时数不对:

在这里输入图片描述

有任何想法吗?谢谢


@Magnas 绿色区域太大了。例如,如果您尝试使用WhatsApp发送消息,如果您写一个小文本,绿色区域就像example3一样。 - Simone Pistecchia
1个回答

13

其中一种可能性是通过 Playground 进行检查

没有太多需要解释的,这个“技巧”是通过不同的堆栈、对齐方式、.fixedSize(horizontal: , vertical:)Color.clear.frame(height:0) 替换 Spacer() 的正确组合完成的。所有这些都使得这个“自动”消息视图扩展基于消息文本。

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())

结果:

输入图片描述

相同的代码被重复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()
        }
    }
}

或者 使用 @ViewBuilder 来创建页眉和页脚

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接