1

In UIKit I can easily set scrollable background pattern for UITableView like this:

tableView.backgroundColor = .init(patternImage: .init(named: "background")!)

Background image in such case is infinitely tiled and is scrollable along with scroll content.

If I try to do the same in SwiftUI:

List {
    ...
}
.background(
    Color(
        UIColor(patternImage: .init(named: "background")!)
    )
)
.scrollContentBackground(.hidden)

background isn't set at all. Similar problem described here: SwiftUI can't create Color by UIColor(patternImage:).

If I try to set background image:

List {
    ...
}
.background(
    Image("background").resizable(resizingMode: .tile)
)
.scrollContentBackground(.hidden)

it is displayed and tiled, but not scrollable.

How to make for SwiftUI List the same behaviour as in UIKit?

2
  • You basically have to hack into the underlying UIKit stuff and set backgroundColor the same way. There is currently no SwiftUI API for this. With a ScrollView you can at least put a Rectangle as large as the scrollable content, filled with ImagePaint, and that will scroll, but not with List. Commented Oct 4 at 15:22
  • @BenzyNeez I want background to fill scroll area. Targeting iOS 17 Commented Oct 5 at 19:52

1 Answer 1

2

You can make the background scroll as the lists scrolls:

struct ContentView: View {
    @State private var offset: CGFloat = 0.0  // 👈 1. Store the offset

    var body: some View {
        List {
            ...
        }
        .background {
            Image(.defaultCard)
                .resizable(resizingMode: .tile)
                .offset(y: offset)  // 👈 2. Apply the offset
        }
        .scrollContentBackground(.hidden)
        .onScrollGeometryChange(for: CGFloat.self) { geometry in
            geometry.contentOffset.y + geometry.contentInsets.top  // 👈 3. Calculate the offset
        } action: { _, newOffset in
            offset = -newOffset  // 👈 4. Update the offset
        }
    }
}

Note that you should make the background size >= content size to fill all the way down. Also, You may want to handle the extra bouncing space of scrollables as well.

Demo

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

1 Comment

Thanks for the tip! Looks as desired. Sadly iOS 18 required to use onScrollGeometryChange, but I found workaround using GeometryReader + onPreferenceChange approach, or may be just to rise target is the right way. Going to experiment with it and also search for solution to neatly respect bounce, and post results here.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.