Home > other >  SwiftUI ScrollView image as background error
SwiftUI ScrollView image as background error

Time:02-03

Thanks for taking your time to help others :)

Bug description:

I can apply a color to the ScrollView background, and adjusts perfectly.

But if I try to set an image as background, the result is not correct, it expands over to the TextField and even safeArea.

I need this because I'm building a chat. And I can't use a ZStack to put the image under the ScrollView, it's complex to explain why.

Simple piece of code to test it.

import SwiftUI

struct ContentView: View {
    @State var text: String = ""

    var body: some View {
        VStack {
            ScrollView() {
                LazyVStack {
                    HStack {
                        Spacer()
                    }
                    ForEach(1..<201, id: \.self) { num in
                        Text("Message \(num)")
                    }
                }
            }
//            .background(Color.red) // Good result, adjusted where I want to
            .background(Image("chatBackground")) // Bad result, expands to TextField and safe area
            
            TextField("Your text here", text: $text)
                .textFieldStyle(.roundedBorder)
                .padding()
        }
        .navigationBarTitleDisplayMode(.inline)
        .navigationTitle("Example app")
    }
}

Results:

  1. Good result (using a color): Good result (using a color)

  2. Bad result (using the image): Bad result (using the image)

Questions

  1. How can I apply an image as background?
  2. Why does it extends down to the very bottom?

EDIT

This is the result of Timmy's answer. Almost the thing but it moves when keyboard appears. enter image description here

CodePudding user response:

You need to set the background of the TextField to white (or whatever color you need):

TextField("Your text here", text: $text)       
    .textFieldStyle(.roundedBorder)
    .padding()
    .background(Color.white)

Update:

In order for the image to bound itself correctly, you need to use the .clipped() modifier after the background one:

.background {
    Image("chatBackground")
        .resizable() //recommended
        .aspectRatio(contentMode: .fill) //recommended
}.clipped()

To make the image ignore the keyboard, you need to wrap the image inside a GeometryReader & add .ignoresSafeArea(.keyboard, edges: .bottom) (Credit to @pawello2222):

.background {
    GeometryReader { _ in
        Image("chatBackground")
            .resizable()
            .aspectRatio(contentMode: .fill)
    }.ignoresSafeArea(.keyboard, edges: .bottom)
}.clipped()
  • Related