1

I have created a package to simply layout a What's New page for an app. The core view is a BulletPointView which is defined as such:

import SwiftUI

public struct BulletPointView: View {
    let title: String
    let image: Image
    let text : String
    
    public init(title: String = "New feature",
                image: Image = Image(systemName: "circle.fill"),
                text: String = "This is a new feature for this app. And this text should wrap.") {
        self.title = title
        self.image = image
        self.text = text
    }
    
    public var body: some View {
        HStack (alignment: .center){
            image
                .font(.title)
                .foregroundColor(Color("AccentColor"))
            VStack (alignment: .leading, spacing: 4){
                Text(title)
                    .fontWeight(.semibold)
                Text(text)
                    .foregroundColor(.secondary)
            }
            .multilineTextAlignment(.leading)
            .font(.subheadline)
            .padding(.bottom, 6)
        }
    }
}

struct BulletPointView_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            BulletPointView(image: Image(systemName: "square.and.pencil"))
            BulletPointView(image: Image(systemName: "hare.fill"))
            BulletPointView(image: Image(systemName: "circle.fill"))
            BulletPointView(image: Image(systemName: "car.2.fill"))
            BulletPointView(image: Image(systemName: "switch.2"))
            BulletPointView(image: Image(systemName: "ellipsis"))
        }
    }
}

This allows the user to select any image to use as a bullet, or defaults to a circle. The problem is that if the images are different widths, the text to the right of the images does not align anymore as seen in the screenshot below.

Screen shot

How do i get all of the text views to line up regardless of the image width?

Thanks!

3
  • First you need to decided a fixed size for Image, after that you can align them. Commented Dec 16, 2021 at 23:30
  • Or, look into Alignment Guides Commented Dec 16, 2021 at 23:38
  • I tried to answer the issue just with Alignment Guides, but that is not enough! You will need to have some kind of size for Image at the end of the day! So if you just use a fixed size for Image like I said, you would not need to use Alignment Guides either. Commented Dec 17, 2021 at 0:08

1 Answer 1

1

Here is the simplest way that is possible. You must to have a size for Image.

PS: You should not use Image as parameter for your view, just use the string of image. I corrected for you.

struct ContentView: View {
    var body: some View {
        VStack {
            BulletPointView(string: "square.and.pencil")
            BulletPointView(string: "hare.fill")
            BulletPointView(string: "circle.fill")
            BulletPointView(string: "car.2.fill")
            BulletPointView(string: "switch.2")
            BulletPointView(string: "swiftPunk")
        }
        .padding()
    }
}

struct BulletPointView: View {
    let title: String
    let string: String
    let text : String
    
    init(title: String = "New feature",
         string: String,
         text: String = "This is a new feature for this app. And this text should wrap.") {
        self.title = title
        self.string = string
        self.text = text
    }
    
    var body: some View {
        HStack (alignment: .center){

            imageFunction(string: string)
                .scaledToFit()
                .frame(width: 50, height: 50)

            VStack (alignment: .leading, spacing: 4){
                Text(title)
                    .fontWeight(.semibold)
                Text(text)
                    .foregroundColor(.secondary)
            }
            .multilineTextAlignment(.leading)
            .font(.subheadline)
            .padding(.bottom, 6)
            
        }
    }
    
   @ViewBuilder func imageFunction(string: String) -> some View {
        
        if (UIImage(systemName: string) != nil) {
             Image(systemName: string)
                .font(.title) 
        }
        else {
             Image(string)
                .resizable()
        }
        
    }
    
}

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you. I had just decided to do the same thing late last night. The only issue I have with passing the image name rather than the image itself is that then the user is locked into using SFSymbols, unless I do a further check here in the code. But I like the solution and marked it as the answer.
@FerdinandRios: I thought you could pass your string and work on incoming string, how ever I edited my code for you that gave you more freedom than before. So you are not locked into using SFSymbols, pass any string you like it, it will work.
Thank you. I actually wound up doing something very similar. The only difference is that I take into account the original aspect ratio of non-sfsymbol images (in case they are not the same height and width) and resize them accordingly so that they always fit the 50p width without distortion.
I know what you mean, I tried that one also, and all the images get bigger size and they were in size, but I didn’t like the result and I decided to give natural size as apple wanted. But this is completely up to you what you need in your app.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.