Skip to content

Instantly share code, notes, and snippets.

@juanarzola
Last active June 5, 2024 18:20
Show Gist options
  • Save juanarzola/ca46d94f5ba6a884b697448e29ada31a to your computer and use it in GitHub Desktop.
Save juanarzola/ca46d94f5ba6a884b697448e29ada31a to your computer and use it in GitHub Desktop.
Workaround for lack of `listRowSelectedBackground` or some way of defining an adaptive background style with your own color
struct ContentView: View {
var body: some View {
List {
SomeRow()
// set the background of the row
.listRowBackground(ListRowBackground())
// .listRowSelectedBackground(ListRowSelectedBackground())
// Oh no, `listRowSelectedBackground` above is not a real API, so list cells don't highlight when selected anymore.
// What do we do now?
// Traverse the UIKit hierarchy and configure cells in it within `ListRowBackground`.
}
}
}
// A background view that traverses the hierarchy to setup the underlying List's UIKit UICollectionViewCell
@MainActor
private struct ListRowBackground: UIViewRepresentable {
func makeUIView(context: Context) -> SelectableBackgroundView {
let selectableView = SelectableBackgroundView()
return selectableView
}
func updateUIView(_ selectableView: SelectableBackgroundView, context: Context) {
// theme has styles
let theme = context.environment.theme
selectableView.backgroundColor = UIColor(theme.groupedlListItemBackgroundColor)
selectableView.selectedBackgroundColor = UIColor(theme.groupedlListItemSelectedBackgroundColor)
}
}
private class SelectableBackgroundView: UIView {
var selectedBackgroundColor: UIColor? = nil {
didSet {
if selectedBackgroundColor != oldValue {
updateCellBackground()
}
}
}
override func didMoveToWindow() {
super.didMoveToWindow()
// the background view should be installed on the cell at this point
updateCellBackground()
}
func updateCellBackground() {
guard let cell = firstSuperview(of: UICollectionViewCell.self) else {
return
}
let selectedBackgroundView = UIView()
selectedBackgroundView.backgroundColor = selectedBackgroundColor
cell.backgroundColor = backgroundColor
cell.selectedBackgroundView = selectedBackgroundView
}
}
// hierarchy-traversal utility
extension UIView {
func firstSuperview<T: UIView>(of clazz: T.Type) -> T? {
guard let superview else { return nil }
if superview.isKind(of: clazz) {
return superview as? T
}
return superview.firstSuperview(of: clazz)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment