列表的SwiftUI背景色Mac OS

zysjyyx4  于 2023-01-04  发布在  Swift
关注(0)|答案(4)|浏览(213)

我在Mac OS中使用列表视图。我试图改变列表视图的背景颜色。但是,这并不像预期的那么容易。
我试着在ListView上使用.background(Color(.red))属性。这没有改变任何东西。
我只能找到对表行有影响的.listRowBackground(Color(.red)),其他背景没有影响。
我准备了一个小演示来演示:
在我看来:

VStack
    {
        List()
        {
            Text("Test")
                .listRowBackground(Color.green)

            Text("Test")
                .listRowBackground(Color.green)

            Text("Test")
                .listRowBackground(Color.green)

        }.background(Color(.red))

    }.background(Color(.red))

这就是我得到的结果:

主背景没有改变。我读到过一个改变UITableView.appearance的解决方案,但这对我来说在Mac OS的SwiftUI中是不可能的。
先谢了

5anewei6

5anewei61#

更新:我发现了一个更好的方法来删除列表的背景,而不会影响整个应用程序:通过使用X1 E0 F1 X。

import Introspect
import SwiftUI

extension List {
  /// List on macOS uses an opaque background with no option for
  /// removing/changing it. listRowBackground() doesn't work either.
  /// This workaround works because List is backed by NSTableView.
  func removeBackground() -> some View {
    return introspectTableView { tableView in
      tableView.backgroundColor = .clear
      tableView.enclosingScrollView!.drawsBackground = false
    }
  }
}

用法:

List {
  ForEach(items) { item in
    ...
  }
}.removeBackground()

旧答案

@Asperi的答案有效,但只有在窗口大小调整后才有效。下面是覆盖List的颜色的另一种解决方案:

extension NSTableView {
  open override func viewDidMoveToWindow() {
    super.viewDidMoveToWindow()

    backgroundColor = NSColor.clear
    enclosingScrollView!.drawsBackground = false
  }
}

一个潜在的缺点是,这将影响应用程序中的所有列表。

ars1skjm

ars1skjm2#

第一张图片显示了问题的起源-默认情况下,使用的滚动视图是不透明的,因此添加的彩色背景在那里,但不可见

因此,解决方案是找到滚动视图并禁用绘图背景

以下是解决这个问题的可能方法或变通方案(但有效,因为所有修改都是通过AppKit API进行的,没有硬编码)。实际上,这与在XIB中关闭用于滚动视图的复选框相同。使用Xcode 11.2 / macOS 10.15进行测试。

struct ScrollViewCleaner: NSViewRepresentable {
    
    func makeNSView(context: NSViewRepresentableContext<ScrollViewCleaner>) -> NSView {
        let nsView = NSView()
        DispatchQueue.main.async { // on next event nsView will be in view hierarchy
            if let scrollView = nsView.enclosingScrollView {
                scrollView.drawsBackground = false
            }
        }
        return nsView
    }
    
    func updateNSView(_ nsView: NSView, context: NSViewRepresentableContext<ScrollViewCleaner>) {
    }
}

extension View {
    func removingScrollViewBackground() -> some View {
        self.background(ScrollViewCleaner())
    }
}

struct TestListBackground: View {
    var body: some View {
            List()
            {
                ForEach(0..<3) { _ in
                    Text("Test")
                        .listRowBackground(Color.green)
                }
                .removingScrollViewBackground() // must be called _inside_ List
                .background(Color.blue)
            }.background(Color.red)
    }
}
egdjgwm8

egdjgwm83#

不幸的是,ListStyle协议没有文档记录,并且.listStyle修饰符的使用非常有限,您可以从CarouselListStyle, DefaultListStyle, GroupedListStyle ,PlainListStyle, SidebarListStyle中选择
尝试用ScrollView结合ForEach来模仿List,这给了你很大的灵活性,缺少的部分很容易写。一旦开发人员可以使用ListStyle,更改代码就很容易了...
示例

及源代码

struct ContentView: View {
    var body: some View {
        HStack(spacing: 0) {
            ScrollView {
                ForEach(0 ..< 4) { idx in
                    VStack(alignment: .leading) {
                        Divider().background(Color.blue)
                        Text("Test \(idx)")
                            .padding(.horizontal, 10)
                            .background(Color.pink)
                        //Divider()
                    }.padding(.bottom, -6)
                }
            }
                .frame(maxWidth: 100)
            .background(Color.gray)

            Color.green
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}
66bbxpm5

66bbxpm54#

Xcode 14Swift 5)中,您可以执行以下操作:

List {
 ...
 }
 .scrollContentBackground(.hidden)
 .background(.red)

这使得ScrollView背景不可见,而List背景现在可以自定义。

相关问题