2

Desired output

Looking for a way to split an HStack in uneven elements, one taking over 1/2 of the screen and the other two 1/4 of the screen (see attachment).

Code:


   struct MyCategoryRow: View {

    var body: some View {
      VStack(alignment: .leading, spacing: 0) {
         HStack(spacing: 0) {
            ForEach(0...2, id: \.self) { block in

                   ColoredBlock()

            }.frame(minWidth: 0, maxWidth: .infinity, alignment: Alignment.topLeading)

      }
    }
  }

So the above code results in an HStack with 3 colored blocks of equal width. I tried enforcing width using UIScreen.main.bounds.width but that approach doesn't adapt to change in orientation. I also tried using GeometryReader like so:

 GeometryReader {  g in
       ColoredBlock().frame(width: block == 0 ? g.size.width * 2 : g.size.width / 2) 
 }

But that didn't work either, seems like the fact that every ColoredBlock will take up 1/3 of the HStack is decided beforehand.

Update with layoutPriority attempt:

struct MyCategoryRow: View {
    var body: some View {
      VStack(alignment: .leading, spacing: 0) {
         HStack(spacing: 0) {
            ForEach(0...2, id: \.self) { block in        
                   ColoredBlock(background: (block == 0) ? Constants.pastel1 : Constants.pastel2).layoutPriority(block == 0 ? 1.0 : 0.5)             
            }.frame(minWidth: 0, maxWidth: .infinity, alignment: Alignment.topLeading)         
      }
    }
  }


struct ColoredBlock: View {
    let background: Color

var body: some View {
    GeometryReader { geometry in
      VStack(spacing: 0){
         HStack {
           Text("Some text").padding(.horizontal, 15).padding(.top, 15)
         }.frame(alignment: .leading)
         VStack(alignment: .leading){
           Text("Some more text").font(.subheadline).fontWeight(.light)
         }.padding(.vertical, 10).padding(.horizontal, 15)
     }.background(self.background)
                .cornerRadius(15)
   }
  }
}

Result:

sugar2code
  • 146
  • 12

2 Answers2

1

I think what you need is .layoutPriority. Set it to 1.0 for the first block and 0.5 for the second and third blocks.

Michael Long
  • 790
  • 6
  • 10
  • Thanks! Updated my question above with my attempt to implement your suggestion. Result was the first block is now taking up about 90% of the screen. Added code for ColoredBlock as well, maybe I'm doing something wrong there. – sugar2code Oct 11 '19 at 17:05
0

What I ended up doing was using GeometryReader in MyCategoryRow instead of ColoredBlock and passing width to ColoredBlock

HStack {
    ForEach(0...2, id: \.self) { block in
        ColoredBlock(background: (block == 0) ? Constants.pastel1 : Constants.pastel2, width: block == 0 ? geometry.size.width / 2 : geometry.size.width / 4, height: 150.0)
     }
}

This works, though now I find myself having to specify a height which I'd prefer not to hardcode. If anyone has a better solution, please let me know!

sugar2code
  • 146
  • 12