How to customize placeholder looks in SwiftUI WidgetKit placeholder?

1.7k views Asked by At

With the way my code is set up, when my Widget is being displayed as a placeholder right before actual data comes in, it looks ugly because of the image placeholder being cut off by the Circle() clip path.

enter image description here

Here's the SwiftUI code (the first Image view is the view in question):

var body: some View {
    VStack {
        HStack(alignment: .center, spacing: 14, content: {
            Image(model.profileIcon).resizable()
                .padding(4)
                .frame(width: 44, height: 44)
                .background(Color("LightColor"))
                .clipShape(Circle())
            VStack(alignment: .leading, spacing: 2, content: {
                Text(model.profileName)
                    .font(.system(size: 16))
                    .bold()
                Text("\(model.practiceToday) today")
                    .font(.system(size: 15)).fontWeight(.regular)
                    .foregroundColor(.gray)
                
            })
            Spacer()
        })
        
        Spacer()
        Divider()
        Spacer()
        
        HStack(alignment: .center, spacing: 10, content: {
            ForEach(0..<7) { i in
                SimpleProgressCircle(
                    progress: CGFloat(model.progress[i]),
                    day: model.weekdays[i],
                    today: i == 6)
            }
        })
        .padding(EdgeInsets(top: 0, leading: 2, bottom: 0, trailing: 2))
    }
    .padding(
        EdgeInsets(top: 17, leading: 15, bottom: 20, trailing: 15))
    .background(Color.foreground)
}

And the placeholder function in the main widget file:

func placeholder(in context: Context) -> WidgetContent {
    return WidgetContent(
        profileID: "",
        profileName: "----",
        profileIcon: "",
        weekdays: ["","","","","","",""],
        progress: [0,0,0,0,0,0,0],
        practiceToday: "--"
    )
}

Ideal outcome: Placeholder just looks like a circle, without the inner rectangle

1

There are 1 answers

0
Shaher Kassam On

One solution would be to declare :

@Environment(\.redactionReasons) private var reasons

And then to use it like this :

    if reasons.isEmpty { //Your regular view
      Image("fallback").resizable()
        .padding(4)
        .frame(width: 44, height: 44)
        .background(Color.gray)
        .clipShape(Circle())
    } else { //Example of placeholder
      Image("fallback").resizable()
        //.padding(4)
        .frame(width: 44, height: 44)
        .background(Color.gray)
        .clipShape(Circle())
    }

or this will do

Image("fallback").resizable()
    .padding(reasons.isEmpty ? 4: 0)