SwiftUI在VStack中的不同对齐文本

时间:2020-01-30 20:26:31

标签: ios swift iphone swiftui

我有一个聊天示例,其中包含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
}

如果文本是log,就可以了示例1:

enter image description here

但是如果很短,示例2:

enter image description here

如果我删除了Spacer()示例3,则可以进行聊天,但是该聊天时间不在右侧:

enter image description here

有什么主意吗?谢谢

1 个答案:

答案 0 :(得分:4)

一种可能性...与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())

结果:

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