skip to Main Content

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

}

2

Answers


  1. 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
            }
        }
    }
    
    Login or Signup to reply.
  2. One possibility is to use LazyVGrid :

    struct HStackCenterCell: View {
        var weatherViewModel = WeatherViewModel();
        let columns: [GridItem] = Array(repeating: .init(.flexible()), count: 3) // 3 columns LazyVGrid
        var body: some View {
            ScrollView(.vertical){
                // Lazy grid to have columns
                LazyVGrid(columns: columns) {
                    ForEach(weatherViewModel.dailyDataArray){
                        DailyCell(dailyData: $0)
                            .background(Color.clear)
                            .padding(10)
                    }
                    
                }
            }
            
        }
    }
    
    struct DailyCell: View {
        let dailyData: DailyData
    
        var body: some View {
            // need to suppress global HStack and Spacers
            HStack { // HStack to align day on left
                Text(dailyData.time)
                    .fontWeight(.semibold)
                    .font(.system(size: 16)).multilineTextAlignment(.leading)
                Spacer()
            }
            // For my tests i used SF symbols
            Image(systemName: dailyData.icon)
                .resizable()
                .scaledToFit()
                .frame(width: 25, height: 25, alignment: .center)
                .multilineTextAlignment(.leading)
            HStack(spacing: 10)
            {
                Text(dailyData.lowtemp + "°")
                    .fontWeight(.regular)
                    .font(.system(size: 16))
                Text(dailyData.hightemp + "°")
                    .fontWeight(.regular)
                    .font(.system(size: 16))
            }
        }
    

    Note : I removed white foreground because my background is white

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search