swiftswiftuivstackhstack

How do I center these images in a straight line inside my HStack in SwiftUI


I have an HStack nested inside of a VStack inside of a ScrollView and I am trying to center the middle photos in a straight line. As you can see in the photo, the pictures are offset based on the size of the text label to the left. (The longer the word, the more the images are offset to the right). I want to have the images be centered in the middle of the HStack in a way where they are all perfectly aligned on top of each other.

The format of the HStack should be (Label - Image - Label) and I want the two labels to be on the far left/right of the image touching the sides of the screen.

I am currently using two Spacer() to do the job but it creates an offset.

Here is what it looks like right now (unaligned):

Here is what it looks like right now (unaligned)

Here is the code of my view that holds the scrollview and vstack:

    ScrollView(.vertical){
                VStack(alignment: .center, spacing: 5){
                    ForEach(weatherViewModel.dailyDataArray){
                        DailyCell(dailyData: $0)
                            .background(Color.clear)
                            .padding(10)
                    }
                }
            }

And here is the code for my CellView

struct DailyCell: View {
    
    let dailyData: DailyData

    var body: some View {
        HStack(alignment: .center){
            Text(dailyData.time)
                .fontWeight(.semibold)
                .foregroundColor(Color(UIColor.white))
                .font(.system(size: 16))
            Spacer()
            Image(dailyData.icon)
                .resizable()
                .scaledToFit()
                .frame(width: 25, height: 25, alignment: .center)
                .multilineTextAlignment(.leading)
            Spacer()
            HStack(spacing: 10){
                Text(dailyData.lowtemp + "°")
                    .fontWeight(.regular)
                    .foregroundColor(Color(UIColor.white))
                    .font(.system(size: 16))
                Text(dailyData.hightemp + "°")
                    .fontWeight(.regular)
                    .foregroundColor(Color(UIColor.white))
                    .font(.system(size: 16))
            }
        }
    }
}

Solution

  • Wrapping everything in a geometryreader and assigning relative width to your textviews should do the trick:

    var body: some View {
        //decide which image to show
        GeometryReader{ readerProxy in <- add this
            HStack(alignment: .center){
                Text(dailyData.time)
                    .fontWeight(.semibold)
                    .foregroundColor(Color(UIColor.white))
                    .font(.system(size: 16))
                    .frame(width: readerProxy.size.width / 3, alignment: .left) <- add this
                Spacer()
                Image(dailyData.icon)
                    .resizable()
                    .scaledToFit()
                    .frame(width: 25, height: 25, alignment: .center)
                    .multilineTextAlignment(.leading)
                Spacer()
                HStack(spacing: 10){
                    Text(dailyData.lowtemp + "°")
                        .fontWeight(.regular)
                        .foregroundColor(Color(UIColor.white))
                        .font(.system(size: 16))
                    Text(dailyData.hightemp + "°")
                        .fontWeight(.regular)
                        .foregroundColor(Color(UIColor.white))
                        .font(.system(size: 16))
                }
                .frame(width: readerProxy.size.width / 3, alignment: .right) <- add this
            }
        }
    }