iOS 16 SwiftUI 列表背景

27

在iOS 16的新 SwiftUI 更新中,List 不再依赖于 UITableView。因此,我们曾经用来将 List 背景色设置为 .clear 的以下代码段现在已经无用:

UITableView.appearance().backgroundColor = .clear

我看到有人使用 introspect 解决了这个问题,但是否有其他更简洁的方法可以实现相同的行为呢?

另外请注意,在 macOS 上,以下代码可以正常运行(已在 Xcode 14 betamacOS Ventura 中测试):

extension NSTableView {
    open override func viewDidMoveToWindow() {
        super.viewDidMoveToWindow()
        backgroundColor = NSColor.clear
        enclosingScrollView!.drawsBackground = false
    }
}
4个回答

35

iOS 16

更新:Xcode 14b3+

只需使用新的modifier:

    List {
        Text("Item 1")
        Text("Item 2")
        Text("Item 3")
    }
    .scrollContentBackground(Color.red)     // << here !!
//    .scrollContentBackground(Color.clear)     // << transparent !!
//    .scrollContentBackground(.hidden)     // << can be combined with above !!

翻译

现在他们使用 UICollectionView 作为后端,因此更新的解决方法是更改相应的背景颜色:

演示

主要部分:

extension UICollectionReusableView {
    override open var backgroundColor: UIColor? {
        get { .clear }
        set { }

        // default separators use same color as background
        // so to have it same but new (say red) it can be
        // used as below, otherwise we just need custom separators
        // 
        // set { super.backgroundColor = .red }

    }
}

struct ContentView: View {
    init() {
        UICollectionView.appearance().backgroundColor = .clear
    }
//...

GitHub上的测试模块


2
这真是太有帮助了,不过当我重写 backgroundColor getter 时,我失去了我的 listRowSeparatorTint(正如您的图片所示)。有什么办法可以恢复它吗? - Darren
1
是的,它们做的事情是一样的,实际上甚至更糟,因为添加SwiftUI行只会将绘图线添加到上下文中,但是Apple会为每个分隔线添加新的UIView。 - Asperi
2
beta 3 中的新 .scrollContentBackground 可以使一切正常工作,无需使用这种解决方法和不同颜色的分隔符。 - Darren
4
我认为新的 beta 版本不允许直接使用 scrollContentBackgroundStyle。它应该被设置为 .hidden,然后与 .background(style) 组合使用。 - Jay Lee
1
无法将类型为“Color”的值转换为预期的参数类型“Visibility”。 - user2619824
显示剩余5条评论

28
为此,我创建了一个自定义标识符来隐藏这个自定义滚动背景。
struct ListBackgroundModifier: ViewModifier {

    @ViewBuilder
    func body(content: Content) -> some View {
        if #available(iOS 16.0, *) {
            content
                .scrollContentBackground(.hidden)
        } else {
            content
        }
    }
}

使用方法:

List {
    ...
}
.modifier(ListBackgroundModifier())

是的,如果你希望应用程序中所有内容都具有相同的样式。但在我的情况下并非如此。 - Marian König
我注意到另一个错误,当列表为空时,它会忽略此修饰符。在这种情况下,只需放置一条细的1像素颜色线,如下所示(将颜色替换为您的背景):Color.red.frame(height: 1).frame(maxWidth: .infinity) .listRowInsets(EdgeInsets()) .listRowSeparatorTint(.clear) .listRowSeparator(.hidden) .listRowBackground(Color.red)并在List上调用:.environment(.defaultMinListRowHeight, 1)。请注意:预览将在没有此修复的情况下工作,但不适用于设备/模拟器。 - frin
是的,谢谢,这是一个非常好的主意,为我定制一个修饰工作。 - undefined

17

iOS 16增加了一个新的修饰符,scrollContentBackground(Visibility),用于自定义可滚动视图(包括List)的背景可见性。

您可以像这样隐藏标准系统背景,这将显示List的背景(如果有提供):

List {
    Text("One")
    Text("Two")
    Text("Three")
}
.background(Image("MyImage"))
.scrollContentBackground(.hidden)

1
我正在使用beta 4,并且传递一个像.red这样的颜色而不是.hidden会出现“无法将类型'Color'的值转换为预期的参数类型'Visibility'”的错误。 - Mark Volkmann
1
@MarkVolkmann 哦,有趣,看起来他们在 beta 4 中删除了使用 Color 的功能。 - Jordan H
谢谢。终于在2023年有东西可以工作了! - user2619824
这是唯一正确的答案。谢谢。 - fish40

10
截至Xcode 15.1版本,工作代码如下:
List {
    Text("1")
    Text("2")
    Text("3")
}
.scrollContentBackground(.hidden)
.background(.purple)

1
这是对我有效的方法。我很难理解为什么他们让改变列表颜色变得如此困难? - Craig_VG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接