skip to Main Content

I am trying to make an HStack, where the views inside it are responsive to the size of the HStack frame. I have gotten this part down, but the issue I have is that the the text in the HStack does not reach the same height as the image beside it. Both containers are the same height — however the text view does not actually reach the full height of its container (as seen by the background).

Does anyone know how to fix this?

 HStack {
    Image(systemName: "globe")
        .resizable()
        .aspectRatio(contentMode: .fit)
        .background(Color.red)
    Text("Globe")
        .font(.system(size: 100))
        .minimumScaleFactor(0.1)
        .background(Color.blue)
    
}.frame(height: 100)

This is the output my current code gives. I am looking to make the text reach the full height of its blue background.

enter image description here

2

Answers


  1. Here is a SwiftUI solution that is quite similar.

    However, it uses hardcoded values.

    Here is an alternate solution using some UIKit.

    struct ContentView: View {
        var body: some View {
            HStack {
                Image(systemName: "globe")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .background(Color.red)
                            
                GeometryReader { geometryReader in
                    MinimumVerticalPaddingSwiftUIView(size: geometryReader.size, text: "Globe")
                        .background(Color.blue)
                }
            }.frame(height: 100)
        }
    }
    
    struct MinimumVerticalPaddingSwiftUIView: UIViewRepresentable {
        typealias UIViewType = MinimumVerticalPaddingLabel
        
        var size: CGSize
        var text: String
    
        func makeUIView(context: Context) -> MinimumVerticalPaddingLabel {
            MinimumVerticalPaddingLabel(text: text, frame: CGRect(origin: CGPoint.zero, size: size))
        }
    
        func updateUIView(_ uiView: MinimumVerticalPaddingLabel, context: Context) {
            // You can update the UIView here if needed.
            // For this example, there's no need to update the UILabel.
        }
    }
    
    class MinimumVerticalPaddingLabel: UIView {
        var text: String = ""
        
        init(text: String, frame: CGRect) {
            super.init(frame: frame)
            self.text = text
            addBackgroundImagetoLayer()
        }
        
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
        
        private func addBackgroundImagetoLayer() {
            let image = UIGraphicsImageRenderer(size: frame.size).image { rendererContext in
                let rect = frame
                UIColor.clear.setFill()
                rendererContext.fill(bounds)
                
                let font = UIFont.systemFont(ofSize: getAppropriateFontSize()) // Change the font size as needed
                let attributes: [NSAttributedString.Key: Any] = [.font: font]
    
                let textSize = text.size(withAttributes: attributes)
                let textX = rect.origin.x + (rect.width - textSize.width) / 2
                let textY = rect.origin.y + (rect.height - textSize.height) / 2
    
                text.draw(at: CGPoint(x: textX, y: textY), withAttributes: attributes)
            }
            
            layer.contents = image.cgImage
        }
        
        func getAppropriateFontSize() -> CGFloat {
            var fontSize: CGFloat = 1
            
            var font = UIFont.systemFont(ofSize: fontSize)
            var attributes: [NSAttributedString.Key: Any] = [.font: font]
            var textSize = text.size(withAttributes: attributes)
            
            while textSize.width <= frame.size.width {
                fontSize += 0.25
                font = UIFont.systemFont(ofSize: fontSize)
                attributes = [.font: font]
                textSize = text.size(withAttributes: attributes)
            }
            
            return fontSize
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    

    The solution does not remove vertical padding but reduces it significantly.

    Output

    Output

    Original

    Original

    Login or Signup to reply.
  2. I believe that space is necessary for certain characters, else they might end up getting clipped.
    Characters using umlaut take that space

    Lowercase characters like g,p etc use that bottom space.

    Characters like back slash etc too.

    If it is a fixed text, there might be some way to find the current text height of the characters used and apply a negative padding like @Md. Ibrahim Hassan has suggested. But I believe that the default space provided be left as is.

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