Home > Back-end >  How do I center these images in a straight line inside my HStack in SwiftUI
How do I center these images in a straight line inside my HStack in SwiftUI

Time:03-07

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

}

CodePudding user response:

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

CodePudding user response:

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

  • Related