Place Text on top of lines separating the colors

Hi, this is my custom view

struct MyView: View {
  var body: some View {
    GeometryReader { geometryReader in
      ZStack {
        VStack(spacing: 0) {
          Rectangle()
            .fill(.red)
            .frame(height: geometryReader.size.height * 0.25)
           
          Rectangle()
            .fill(.orange)
            .frame(height: geometryReader.size.height * 0.5)
           
          Rectangle()
            .fill(.yellow)
            .frame(height: geometryReader.size.height * 0.25)
        }
         
        VStack {
          Spacer()
          Image(systemName: "figure.wave")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(height: geometryReader.size.height * 0.8)
        }
      }
    }
    .frame(maxWidth: 100, maxHeight: 200)
    .background(.white.opacity(0.7))
    .cornerRadius(5)
    .shadow(color: Color.gray.opacity(0.7), radius: 8, x: 0, y: 0)
    .padding()
  }
}

struct MyView_Previews: PreviewProvider {
  static var previews: some View {
    MyView()
  }
}

I am not sure what the best approach for this is. I want to place some text (please see image).

I was thinking adding another VStack at the bottom but i am not sure how i can position it correctly.

Thoughts?

Answered by Claude31 in 738005022

You can use a ZStack:

  var body: some View {
    GeometryReader { geometryReader in
      ZStack {
        VStack(spacing: 0) {
            ZStack(alignment: .bottom) {
                Rectangle()
                    .fill(.red)
                    .frame(height: geometryReader.size.height * 0.25)
                Text("Text1")
                    .background(.blue.opacity(0.7))
            }

            ZStack(alignment: .bottom) {
                Rectangle()
                    .fill(.orange)
                    .frame(height: geometryReader.size.height * 0.5)
                Text("Text2")
                    .background(.blue.opacity(0.7))
            }

          Rectangle()
            .fill(.yellow)
            .frame(height: geometryReader.size.height * 0.25)
        }

Problem is that Text does not appear at front.

I used a trick to put the text above the figure while keeping colored rectangles below:

struct MyView: View {
    var body: some View {
        GeometryReader { geometryReader in
            ZStack {
                VStack(spacing: 0) {
                    ZStack(alignment: .bottom) {
                        Rectangle()
                            .fill(.red)
                            .frame(height: geometryReader.size.height * 0.25)
                    }
                    
                    ZStack(alignment: .bottom) {
                        Rectangle()
                            .fill(.orange)
                            .frame(height: geometryReader.size.height * 0.5)
                    }
                    
                    Rectangle()
                        .fill(.yellow)
                        .frame(height: geometryReader.size.height * 0.25)
                }
                
                VStack {
                    Spacer()
                    Image(systemName: "figure.wave")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(height: geometryReader.size.height * 0.8)
                }
                
                // Draw again to position Texts at front
                VStack(spacing: 0) {
                    ZStack(alignment: .bottom) {
                        Rectangle()
                            .fill(.clear)   // It will not show
                            .frame(height: geometryReader.size.height * 0.25)
                        Text("Text1")
                            .background(.blue.opacity(0.7))
                    }
                    
                    ZStack(alignment: .bottom) {
                        Rectangle()
                            .fill(.clear)
                            .frame(height: geometryReader.size.height * 0.5)
                        Text("Text2")
                            .background(.blue.opacity(0.7))
                    }
                    Rectangle()
                        .fill(.clear)
                        .frame(height: geometryReader.size.height * 0.25)
                }
            }
        }
        .frame(maxWidth: 100, maxHeight: 200)
        .background(.white.opacity(0.7))
        .cornerRadius(5)
        .shadow(color: Color.gray.opacity(0.7), radius: 8, x: 0, y: 0)
        .padding()
    }
}

You just have to select the perfect blue…

Accepted Answer

You can use a ZStack:

  var body: some View {
    GeometryReader { geometryReader in
      ZStack {
        VStack(spacing: 0) {
            ZStack(alignment: .bottom) {
                Rectangle()
                    .fill(.red)
                    .frame(height: geometryReader.size.height * 0.25)
                Text("Text1")
                    .background(.blue.opacity(0.7))
            }

            ZStack(alignment: .bottom) {
                Rectangle()
                    .fill(.orange)
                    .frame(height: geometryReader.size.height * 0.5)
                Text("Text2")
                    .background(.blue.opacity(0.7))
            }

          Rectangle()
            .fill(.yellow)
            .frame(height: geometryReader.size.height * 0.25)
        }

Problem is that Text does not appear at front.

I used a trick to put the text above the figure while keeping colored rectangles below:

struct MyView: View {
    var body: some View {
        GeometryReader { geometryReader in
            ZStack {
                VStack(spacing: 0) {
                    ZStack(alignment: .bottom) {
                        Rectangle()
                            .fill(.red)
                            .frame(height: geometryReader.size.height * 0.25)
                    }
                    
                    ZStack(alignment: .bottom) {
                        Rectangle()
                            .fill(.orange)
                            .frame(height: geometryReader.size.height * 0.5)
                    }
                    
                    Rectangle()
                        .fill(.yellow)
                        .frame(height: geometryReader.size.height * 0.25)
                }
                
                VStack {
                    Spacer()
                    Image(systemName: "figure.wave")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(height: geometryReader.size.height * 0.8)
                }
                
                // Draw again to position Texts at front
                VStack(spacing: 0) {
                    ZStack(alignment: .bottom) {
                        Rectangle()
                            .fill(.clear)   // It will not show
                            .frame(height: geometryReader.size.height * 0.25)
                        Text("Text1")
                            .background(.blue.opacity(0.7))
                    }
                    
                    ZStack(alignment: .bottom) {
                        Rectangle()
                            .fill(.clear)
                            .frame(height: geometryReader.size.height * 0.5)
                        Text("Text2")
                            .background(.blue.opacity(0.7))
                    }
                    Rectangle()
                        .fill(.clear)
                        .frame(height: geometryReader.size.height * 0.25)
                }
            }
        }
        .frame(maxWidth: 100, maxHeight: 200)
        .background(.white.opacity(0.7))
        .cornerRadius(5)
        .shadow(color: Color.gray.opacity(0.7), radius: 8, x: 0, y: 0)
        .padding()
    }
}

You just have to select the perfect blue…

Place Text on top of lines separating the colors
 
 
Q