HomeiOS DevelopmentPicture would not fill whole widget

Picture would not fill whole widget


I’m making an attempt to construct a widget for my app to point out countdowns. Within the background, it ought to have a picture chosen by the person. All the things within the widget works largely fantastic besides that the picture isn’t filling the complete widget. Initially, I assumed the ZStack was solely taking as a lot house because the VStack with the textual content wanted, however I’ve tried commenting the VStack and it nonetheless has the house round it.
I’ve tried asking ChatGPT, Claude and Gemini, however all they inform me is so as to add .scaledToFill(), .body(maxWidth: .infinity, maxHeight: .infinity), or .ignoresSafeArea(), however these do not appear to work.
If I take away the .resizable(), the picture will get means greater than the widget.
That is the code I’ve:

struct SimpleEntry: TimelineEntry {
    let date: Date
    let configuration: ConfigurationAppIntent
}

let backgroundGradient = LinearGradient(
    colours: [Color.red, Color.blue],
    startPoint: .high, endPoint: .backside)

struct CountdownsEntryView : View {
    var entry: Supplier.Entry
    
    func daysLeftText(days_left: Int) -> String {
        var days_left_text: String = "(days_left) days left"

        if days_left == 1 {
            days_left_text = "(days_left) day left"
        }
        else if days_left == 0 {
            days_left_text = "In the present day!"
        }
        else if days_left < 0 {
            days_left_text = "(abs(days_left)) days in the past"
        }
        
        return days_left_text
    }

    var physique: some View {
        ZStack {
            // Background picture
            if let widgetImg = entry.configuration.countdown?.picture,
               let uiImg = UIImage(knowledge: widgetImg) {
                Picture(uiImage: uiImg)
                    .resizable()
                    .scaledToFill()
            } else {
                // Fallback gradient if no picture
                LinearGradient(
                    colours: [Color.purple, Color.blue],
                    startPoint: .high,
                    endPoint: .backside
                )
            }
            
            // Textual content overlay
            VStack(spacing: 30) {
                Textual content(entry.configuration.countdown?.title ?? "Default")
                    .foregroundStyle(.white)
                    .font(.largeTitle)
                    .minimumScaleFactor(0.01)
                    .lineLimit(1)
                    .shadow(
                            colour: Colour.major.opacity(0.5), /// shadow colour
                            radius: 3, /// shadow radius
                            x: 0, /// x offset
                            y: 2 /// y offset
                        )

                Textual content(daysLeftText(days_left: daysLeft(date: entry.configuration.countdown?.date ?? Date())))
                    .foregroundStyle(.white)
                    .font(.title)
                    .minimumScaleFactor(0.01)
                    .lineLimit(1)
                    .shadow(
                            colour: Colour.major.opacity(0.5), /// shadow colour
                            radius: 3, /// shadow radius
                            x: 0, /// x offset
                            y: 2 /// y offset
                        )
            }
            .padding()
        }
    }
}

struct Countdowns: Widget {
    let sort: String = "Countdowns"

    var physique: some WidgetConfiguration {
        AppIntentConfiguration(sort: sort, intent: ConfigurationAppIntent.self, supplier: Supplier()) { entry in
            CountdownsEntryView(entry: entry)
                .containerBackground(.fill, for: .widget)
//                .background(backgroundGradient)
        }
    }
}

When including the picture to the app, that is how I course of it:

extension UIImage {
    func croppedToSquare() -> UIImage {
        // If picture is already sq., return as-is
        if measurement.width == measurement.peak {
            return self
        }
        
        // Decide the aspect size (use the smaller dimension)
        let sideLength = min(measurement.width, measurement.peak)
        
        // Calculate the crop rectangle (centered)
        let xOffset = (measurement.width - sideLength) / 2
        let yOffset = (measurement.peak - sideLength) / 2
        let cropRect = CGRect(x: xOffset, y: yOffset, width: sideLength, peak: sideLength)
        
        // Crop the picture
        guard let cgImage = self.cgImage,
              let croppedCGImage = cgImage.cropping(to: cropRect) else {
            return self
        }
        
        return UIImage(cgImage: croppedCGImage, scale: self.scale, orientation: self.imageOrientation)
    }

    func resizedForWidget(maxWidth: CGFloat = 400) -> UIImage {
        // First crop to sq.
        let squareImage = croppedToSquare()
        
        // If already sufficiently small, return as-is
        if squareImage.measurement.width <= maxWidth {
            return squareImage
        }
        
        // Resize to maxSize
        let newSize = CGSize(width: maxWidth, peak: maxWidth)
        let renderer = UIGraphicsImageRenderer(measurement: newSize)
        return renderer.picture { _ in
            squareImage.draw(in: CGRect(origin: .zero, measurement: newSize))
        }
    }
    
    // Various technique with extra aggressive compression for widgets
    func optimizedForWidget() -> UIImage {
        // Resize to most 300px for widgets (extra conservative)
        let resized = resizedForWidget(maxWidth: 300)
        
        // Convert to JPEG and again to cut back file measurement
        guard let jpegData = resized.jpegData(compressionQuality: 0.8),
              let compressedImage = UIImage(knowledge: jpegData) else {
            return resized
        }
        
        return compressedImage
    }
}

And that is the way it appears to be like within the widget:
Picture would not fill whole widget

Am I lacking one thing? May anybody assist me with this?

Thanks.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments