Miles
Miles

Reputation: 574

How to customize placeholder looks in SwiftUI WidgetKit placeholder?

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

Upvotes: 4

Views: 2101

Answers (3)

Sanaullah Javeid
Sanaullah Javeid

Reputation: 317

According to my recent experience, I've noted that any image in the whole assets with wrong dimensions will cause the widget to do ridiculous things even if you are not using that image in your widget. So, make sure to use supported dimensions

Upvotes: 0

koliush
koliush

Reputation: 324

In my case, I found the solution and it works for me. I had a few @Parameter and some of them didn't have default values, I set default values and all worked fine.

Upvotes: 0

Shaher Kassam
Shaher Kassam

Reputation: 282

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)

Upvotes: 1

Related Questions