Align Text with padding SwiftUI
Asked Answered
C

1

5

I am creating a view that looks like this -

required view

I am struggling to align the summary text with the text inside the image overlay.

I would like the leading edge of Research to align with the leading edge of My experience.

At the moment my view is rendering as

first attempt

As you can see text view is too close to the leading edge.

I have tried adding .padding() but the view changes to

second attempt

How can I properly inset the text so these 2 components line up?

import SwiftUI

struct ContentView: View {
  var body: some View {
    ZStack {
      FeaturedContentCard()
        .frame(minHeight: 100)
    }.padding()
  }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}

struct FeaturedContentCard: View {
  var body: some View {
    VStack {
      ImageWithTextOverlayView(image: "featured_image", text: "My experience with EAP and Income Protection")
      ContentCardSummary(text: "Research shows that our social enviroment significantly impacts our biology")
        .padding(.all)
      ContentCardMetaView(readTime: "10 min read", name: "Jessica Bell")
    }
    .padding(.bottom, 16)
    .background(Color.white)
    .feedItemContainer()
  }
}


struct ImageWithTextOverlayView: View {

  private(set) var image: String
  private(set) var text: String

  var body: some View {
    Image(image)
      .resizable()
      .aspectRatio(contentMode: .fit)
      .frame(minWidth: 0, maxWidth: .infinity)
      .overlay(LinearGradient(gradient: Gradient(colors: [Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.6536279966)), Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0))]), startPoint: .bottom, endPoint: .top))
      .overlay(
        Text(text)
          .foregroundColor(Color.white)
          .font(.title)
          .padding(),
        alignment: .bottomLeading
    )
  }
}

struct ContentCardSummary: View {
  private(set) var text: String
  var body: some View {
    Text(text)
      .frame(alignment: .leading)
      .foregroundColor(Color(#colorLiteral(red: 0.2901960784, green: 0.2901960784, blue: 0.2901960784, alpha: 1)))
  }
}


struct FeedItemContainer: ViewModifier {
  func body(content: Content) -> some View {
    content
      .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
      .customShadow()
  }
}

struct BenefexShadow: ViewModifier {
  func body(content: Content) -> some View {
    content
      .shadow(color: Color(.init(red: 0.18, green: 0.18, blue: 0.18, alpha: 0.16)).opacity(1), radius: 4, x: 0, y: 1)
      .shadow(color: Color(.init(red: 0.18, green: 0.18, blue: 0.18, alpha: 0.1)).opacity(1), radius: 60, x: 0, y: 4)
      .shadow(color: Color(.init(red: 0.18, green: 0.18, blue: 0.18, alpha: 0.16)).opacity(1), radius: 4, x: 0, y: 1)
  }
}


extension View {

  func customShadow() -> some View {
    self.modifier(BenefexShadow())
  }

  func feedItemContainer() -> some View {
    self.modifier(FeedItemContainer())
  }
}

struct AvatarView: View {
  var body: some View {
    Image("profile_pic")
      .resizable()
      .aspectRatio(contentMode: .fill)
      .frame(width: 40, height: 40)
      .clipShape(Circle())
      .overlay(
        Circle()
          .stroke(Color.white, lineWidth: 2)
    )
      .customShadow()
  }
}

struct ContentCardMetaView: View {
  private(set) var readTime: String
  private(set) var name: String
  var body: some View {
    HStack(spacing: 8) {
      AvatarView()
      VStack(alignment: .leading) {
        Text(readTime)
          .font(.subheadline)
          .foregroundColor(Color(#colorLiteral(red: 0.2901960784, green: 0.2901960784, blue: 0.2901960784, alpha: 1)))
        Text(name)
          .fontWeight(.medium)
          .foregroundColor(Color(#colorLiteral(red: 0.2980392157, green: 0.1843137255, blue: 0.737254902, alpha: 1)))
      }
      Spacer()
      Button(action: { }) {
        Image(systemName: "ellipsis")
          .font(.system(size: 24))
          .foregroundColor(Color(#colorLiteral(red: 0.7803921569, green: 0.7803921569, blue: 0.7803921569, alpha: 1)))
          .rotationEffect(.degrees(-90))
      }

    }
  }
}

Cesaro answered 29/5, 2020 at 17:16 Comment(0)
P
8

Here is fix. Tested with Xcode 11.4 / iOS 13.4

demo

1) Remove padding at top layer, so

  ImageWithTextOverlayView(image: "large_image", text: "My experience with EAP and Income Protection")
  ContentCardSummary(text: "Research shows that our social enviroment significantly impacts our biology")
  ContentCardMetaView(readTime: "10 min read", name: "Jessica Bell")

2) Correct alignment of summary, as

struct ContentCardSummary: View {
  private(set) var text: String
  var body: some View {
    Text(text)
      .frame(maxWidth: .infinity, alignment: .leading) // << full width
      .padding() // << same padding as above text
      .foregroundColor(Color(#colorLiteral(red: 0.2901960784, green: 0.2901960784, blue: 0.2901960784, alpha: 1)))
  }
}
Petasus answered 29/5, 2020 at 17:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.