ScrollView文本对齐SwiftUI

3
我有一个垂直的ScrollView,里面有一个ForEach循环,其中包含HStack,其中有TextImage和两个Text。我想让每一行的项目保持对齐。我尝试将其包装在一个VStack中,并使用alignment .leading对齐,但没有效果。我的问题是文本不对齐。因为我对SwiftUI还很陌生,所以任何帮助都将不胜感激。

Issue

ScrollView(.vertical) {
    ForEach(self.daily.forecast, id: \.date) { forecast in
        HStack (spacing : 10){
            Text(forecast.date ?? "")
                .fontWeight(.bold)
            Spacer()
            RequestImage(Url("IMAGE_URL"))
                .aspectRatio(contentMode: .fit)
                .frame(width: 30, height: 30)
                .clipped()
            Spacer()
            Text("\(forecast.maxTemp)")
                .fontWeight(.bold)
            Text("\(forecast.minTemp)")
                .fontWeight(.bold)
        }
    }
}
.padding(.all, 15)
.onAppear() {
    authorize {_ in
        loadForecast()
    }
}

更新: 我已经接近一点了,但是事情还没有对齐到我想要的位置。
ScrollView(.vertical) {
    ForEach(self.daily.forecast, id: \.date) { forecast in
        HStack (spacing : 10){
            Text(date)
                .font(.title3)
                .fontWeight(.bold)
                .frame(minWidth: 45)
            Spacer()
            RequestImage(Url("IMAGE_URL"))
                .aspectRatio(contentMode: .fit)
                .frame(width: 35, height: 35)
                .frame(minWidth: 50)
                .clipped()
            Spacer()
            Text(maxTemp)
                .font(.title3)
                .fontWeight(.bold)
                .frame(minWidth: 45)
            Text(minTemp)
                .font(.title3)
                .fontWeight(.bold)
                .foregroundColor(Color.secondary)
                .frame(minWidth: 45)
        }
        .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
    }
}
.padding(.all, 15)
.onAppear() {
    authorize {_ in
        loadForecast()
    }
}

enter image description here


1
这是因为每个 Text() 的长度不同。我建议在每个 Text 的框架上设置宽度或最小宽度。 - nicksarno
你想让它们如何对齐并不清楚?你能添加一些演示/草图/模型吗? - Asperi
@Asperi,我添加了一段代码示例,展示我需要的效果。我已经接近目标,但是对齐看起来仍然很不协调和错误。 - cole
@nicksarno,它确实有所帮助,但并没有解决我的问题。 - cole
@Cole 给HStack中的每个项目添加一个带有颜色的.background(),这样你就可以看到框架大小不同的地方了。 - nicksarno
3个回答

3

以下是可能解决方案的演示。使用Xcode 12.4 / iOS 14.4准备

demo

struct DemoWeatherLayout: View {
    private var dayOfTheWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sut"]
    var body: some View {
        ScrollView {
            VStack {
                ForEach(dayOfTheWeek, id: \.self) {
                    WeatherRowView(day: $0, 
                       icon: ["sun.max", "cloud.sun", "cloud", "cloud.snow"].randomElement()!,
                       low: Array(-5..<0).randomElement()!, 
                       high: Array(1..<15).randomElement()!)
                }
            }.padding()
        }
    }
}

struct WeatherRowView: View {
    var day: String
    var icon: String
    var low: Int
    var high: Int

    var body: some View {
        HStack {
            Text(day)
                .frame(maxWidth: .infinity, alignment: .leading)
            Image(systemName: icon)
                .frame(maxWidth: .infinity, alignment: .leading)
            HStack {
                Text("+XXº").foregroundColor(.clear)
                    .overlay(Text(String(format: "%+d", low)), alignment: .leading)
                Text("+XXº").foregroundColor(.clear)
                    .overlay(Text(String(format: "%+d", high)), alignment: .leading)
            }
        }
    }
}

0

三个建议:

  • HStack中添加alignment参数:

    HStack(alignment: .lastTextBaseline, spacing: 10) { ... //其他选项:.top,.center,.firstTextBaseline...

  • Spacer中添加minLength参数:

    Spacer(minLength: 0)但是在HStack中使用spacing: 10有点多余。您可以删除spacing: 10并使用Spacer(minLength: 10)

  • Text("\(forecast.minTemp)").fontWeight(.bold)之后添加一个Spacer(minLength: 0)


0

我将接受@Asperi的答案作为正确答案。UI确实已经改变,以更好地适应所述标签等。感谢大家的帮助。代码非常丑陋,但是可以工作。不确定是否100%正确。

HStack (spacing: 10){
    Text(date)
        .font(.title3)
        .fontWeight(.bold)
        .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
    Spacer()
    RequestImage(Url("IMAGE_URL_HERE"))
        .aspectRatio(contentMode: .fit)
        .frame(width: 35, height: 35)
        .frame(minWidth: 55)
        .clipped()
    Spacer()
    Text(maxTemp)
        .font(.title3)
        .fontWeight(.bold)
        .frame(minWidth: 50)
        .background(Color.orange)
        .cornerRadius(5)
    Text(minTemp)
        .font(.title3)
        .fontWeight(.bold)
        .frame(minWidth: 50)
        .background(Color.blue)
        .cornerRadius(5)
}

enter image description here


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