【问题标题】:How do I modify the background color of a List in SwiftUI?如何在 SwiftUI 中修改 List 的背景颜色?
【发布时间】:2019-10-24 08:28:38
【问题描述】:

我正在尝试在 SwiftUI 中重新创建使用 UIKit 构建的 UI,但遇到了一些小问题。

我想在这里更改List 的颜色,但似乎没有任何属性可以按我的预期工作。示例代码如下:

struct ListView: View {
    @EnvironmentObject var listData: ListData

       var body: some View {
        NavigationView {
            List(listData.items) { item in
                ListItemCell(item: item)
            }
            .content.background(Color.yellow) // not sure what content is defined as here
            .background(Image("paper-3")) // this is the entire screen 
        }
    }
}

struct ListItemCell: View {
    let item: ListItem

    var body: some View {

        NavigationButton(destination: Text(item.name)) {
            Text("\(item.name) ........................................................................................................................................................................................................")
                .background(Color.red) // not the area I'm looking for
        }.background(Color.blue) // also not the area I'm looking for
    }
}

【问题讨论】:

标签: swift swiftui


【解决方案1】:

我能够使用 colorMultiply(Color:) 让整个列表更改颜色。只需将此修饰符添加到列表视图的末尾,然后填充会将表格推到设备边缘。例如:

List {...}.colorMultiply(Color.green).padding(.top)

https://www.hackingwithswift.com/quick-start/swiftui/how-to-adjust-views-by-tinting-and-desaturating-and-more

【讨论】:

  • 它有效,但它与单元格的颜色混淆 - 即只是尝试使用红色文本作为列表项 - 它们变成黑色。
  • 是的,不幸的是,混合不是你想要的。您希望它分层,背景视图颜色作为背景,然后单元格颜色和/或文本颜色位于其之上
  • 不适用于深色主题。无用的解决方案。
【解决方案2】:

好的,我找到了为列表行着色的解决方案:

struct TestRow: View {

    var body: some View {
        Text("This is a row!")
        .listRowBackground(Color.green)
    }
}

然后在正文中:

List {
    TestRow()
    TestRow()
    TestRow()
}

这按我的预期工作,但我还没有弄清楚如何删除行之间的分隔线......

【讨论】:

  • SwiftUI 现在存在令人难以置信的错误,当我使用这样的代码并对我的列表项进行硬编码时,这很有效。当我异步加载数据时,它不再工作了..
  • 是的,有点痛苦。不过玩起来很有趣。应该很快就会变得更平滑,希望
  • @MariusWaldal 你找到如何更改剖面视图背景颜色了吗?
  • @andromedainiative Do List { ForEach(items, id: \.self) { item in Text(item).listRowBackground(Color.green) } 代替,然后就可以了。
  • 我遇到了一个非常愚蠢的问题,即 .listRowBackground() 修饰符必须在 .contextMenu() 修饰符之后,否则它将不起作用。 Xcode 12.0.1
【解决方案3】:

如果尝试使用 .listRowBackground 并应用 .padding 使用 SwiftUI 创建浮动类型单元格,有人可能会发现这很有用

var body: some View {
    NavigationView {
        List {
            ForEach (site) { item in
                HStack {
                    Text(String(item.id))

                    VStack(alignment: .leading) {
                        Text(item.name)
                        Text(item.crop[0])
                    }

                }.listRowBackground(Color.yellow)
                      .padding(.trailing, 5)
                      .padding(.leading, 5)
                      .padding(.top, 2)
                      .padding(.bottom, 2))
            }
        }
            .navigationBarTitle(Text("Locations"))
    }
}

【讨论】:

  • 嗨@caleb81389,它对我有用,但不适用于空行。你知道为什么吗?
  • 不抱歉。我不知道如何将其应用于空行。也许您可以人为地将空白文本“”放在标签或其他东西中......?除此之外 SwiftUI 有点做它想做的事情,类似的事情会让别人比我更容易回答。
  • 如果你弄明白了告诉我!
【解决方案4】:

我认为 listRowPlatterColor 修饰符应该这样做,但不是从 Xcode 11 Beta 11M336w 开始

var body: some View {
    List(pokemon) { pokemon in
        PokemonCell(pokemon: pokemon)
            .listRowPlatterColor(.green)
    }
}

【讨论】:

  • listRowPlatterColor 现已弃用,仅适用于 watchOS。
【解决方案5】:

我不知道连接是什么,但如果你用Form 包装列表,它就可以工作。

Form {
     List(viewModel.currencyList, id: \.self) { currency in
        ItemView(item: currency)
     }
      .listRowBackground(Color("Primary"))
      .background(Color("Primary"))
}

【讨论】:

  • Caleb 指出 listRowBackground 不应应用于列表,而应应用于行项目本身。此外,您应该能够只做 Color("Primary") 而不是强制展开 UIColor :)
  • 这行得通,但是,我在列表中有一个部分标题,该标题现在不是sticky--它随列表一起移动:(。
【解决方案6】:

您可以通过更改UITableView 的外观来做到这一点。

UITableView.appearance().backgroundColor = UIColor.clear

只需将此行放入AppdelegatedidFinishLaunchingWithOptions 方法中。 代替UIColor.clear 设置您想在list 的背景颜色中添加的任何颜色。

【讨论】:

  • 它可以工作,但它不会删除实际显示的行下的白色背景
  • 它完成了这项工作:UITableViewCell.appearance().backgroundColor = .clear
  • Mac 有解决方案吗?
【解决方案7】:

struct ContentView: View {

    var strings = ["a", "b"]

    var body: some View {

        List {
            ForEach(strings, id: \.self) { string in
                Text(string)
            }.listRowBackground(Color.green)
        }
    }
}

【讨论】:

  • 它可以工作,但我仍然停留在弄清楚如何更改列表本身的背景。
  • 这也是唯一对我有用的。我认为重要的是要强调您必须拥有 List { ForEach(elements) { }} 而不是 List(elements) { } 才能使此修饰符起作用。
  • 疯狂的是,您将数据指定到列表中的方式使此修饰符不起作用。在 SwiftUI 中看到这种错误,并不能很好地了解它。
  • 这已在 iOS 15 中得到修复。listRowBackground 适用于 List(elements)List { ForEach(elements) { 中的项目
【解决方案8】:

我启发了一些用于配置每页 NavigationView 导航栏样式的配置器,并编写了一些简单的 UITableView 每页配置器不使用 UITableView.appearance() 全局方法

   import SwiftUI

    struct TableViewConfigurator: UIViewControllerRepresentable {

        var configure: (UITableView) -> Void = { _ in }

        func makeUIViewController(context: UIViewControllerRepresentableContext<TableViewConfigurator>) -> UIViewController {

            UIViewController()
        }

        func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<TableViewConfigurator>) {

            let tableViews = uiViewController.navigationController?.topViewController?.view.subviews(ofType: UITableView.self) ?? [UITableView]()

            for tableView in tableViews {
                self.configure(tableView)
            }
        }
    }

然后有 UIView 扩展需要找到所有 UITableViews

extension UIView {
    func subviews<T:UIView>(ofType WhatType:T.Type) -> [T] {
        var result = self.subviews.compactMap {$0 as? T}
        for sub in self.subviews {
            result.append(contentsOf: sub.subviews(ofType:WhatType))
        }
        return result
    }
}

最后的用法是:

List {

}.background(TableViewConfigurator {
    $0.backgroundColor = .red
})

也许应该改进一件事,那就是使用 navigationController?.topViewController 使其即使在视图控制器层次结构中没有 navigationController 也能工作

【讨论】:

    【解决方案9】:

    对我来说,在 SwiftUI 中更改 List 背景的完美解决方案是:

    struct SomeView: View {
        init(){
        UITableView.appearance().backgroundColor = UIColor(named: "backgroundLight")
          }
    ...
    
    }
    

    【讨论】:

      【解决方案10】:

      这会将整个列表的背景设置为绿色:

      init() {
         UITableView.appearance().separatorStyle = .none
         UITableViewCell.appearance().backgroundColor = .green
         UITableView.appearance().backgroundColor = .green
      }
      

      【讨论】:

      • 我如何在不同的列表中改变它?我将此应用于一个选项卡中的一个列表,这影响了另一个选项卡视图中的另一个列表。
      • 不错,也可以使用:UITableView.appearance().separatorColor = .darkGray
      • @glothais-kwl 你找到“重置”TableView 外观的方法了吗!?像你一样,我希望在某些视图上而不是在所有视图上都这样做,并且需要一种根据显示的视图重置它的方法。
      • 令人愤怒的是,如此重要的更改(因为否则您的列表将漂浮在白色背景上)如此脱离上下文而无法访问。也可以像这样使用: List { }.onAppear{ UITableView.appearance().separatorStyle = .none UITableViewCell.appearance().backgroundColor = .green UITableView.appearance().backgroundColor = .green }
      • @glothais-kwl 你可以使用UIAppearance.appearanceWhenContainedInInstancesOfClasses: 并传递UIHostingController 的特定子类,你将使用它来呈现这个确切的SwiftUI 视图。
      【解决方案11】:

      列表还不完善。

      一种选择是像这样使用它 -> List { ForEach(elements) { }} 而不是 List($elements)

      就我而言,这是迄今为止效果最好的。 就像@FontFamily 所说,它不应该破坏任何List 默认行为,例如滑动。

      【讨论】:

      • 这会杀死嵌套列表项的 onDelete 和 onMove 功能。
      • 我给出的第二个例子是否会杀死它?我认为List { ForEach(elements) } 应该没问题吧?
      • 你是对的 - 它确实适用于你给出的第二个例子。
      【解决方案12】:

      .colorMultiply(...)

      您可以选择.colorMultiply(Color.yourColor) 修饰符。

      警告这不会改变颜色!这只会将Multiply 修饰符应用于当前颜色。请在采取任何行动之前阅读问题,因为您可能正在寻找:“如何在 SwiftUI 中更改列表的背景颜色”,这对您不起作用。 ❄️

      示例:

      List (elements, id:\.self ) { element in
      
           Text(element)
      
      }
      .colorMultiply(Color.red) <--------- replace with your color
      

      【讨论】:

      • 效果很好,但是如果用户切换到暗模式,它会惨遭失败。我希望这是 SwiftUI 错误
      • 这只是覆盖了一个冷却器和乘法器,它不会改变当前颜色
      • @ManeManero 我想知道您是否阅读了帖子的问题:“如何在 SwiftUI 中修改列表的背景颜色?”这不会改变颜色,它会修改它。对于暗模式,是的,您需要为特定更改添加更多逻辑/条件。
      • 这会弄乱行背景颜色
      • 在深色主题下不能正常工作,这个解决方案没用。
      【解决方案13】:

      SwiftUI中有一个说法:listRowBackground(),但是如果直接用List来迭代数据集合,就不行了。

      这是我的解决方法:

          List {
              // To make the background transparent, we have we use a ForEach as a wrapper
              ForEach(files) {file in
                  Label(
                      title: { Text(file.name ?? fileOptionalFiller).lineLimit(listRowTextLineLimit) },
                      icon: { AppIcon.doc.foregroundColor(.primary) }
                  )
              }
              .listRowBackground(Color.primary.colorInvert())
          }
      

      基本上,如果您在 List 中使用 ForEach,则 listRowBackground() 可以工作。

      【讨论】:

        【解决方案14】:

        如果有人来这里寻找 iPhone X/11 上横向背景而不是全宽的解决方案,请尝试:

        .listRowBackground(Color("backgroundColour").edgesIgnoringSafeArea(.all))
        

        【讨论】:

          【解决方案15】:

          Xcode 12.4 版

          Background 属性对我有用,但必须使用 Opacity。 没有 opacity 是行不通的。

          List {
                      ForEach(data, id: \.id) { (item) in
                          ListRow(item)
                              .environmentObject(self.data)
                      }
                  }
                  .background(Color.black)
                  .opacity(0.5)
          

          【讨论】:

          • 虽然这确实有效,但它也使列表变得透明。我尝试了opacity(0.5)opacity(1)opacity(0),但没有给出结果,其中列表行存在且列表背景为所需颜色
          • 这是一个无关紧要的答案,也不行。
          【解决方案16】:
          struct Details: View {
          
              var body: some View {
                  Spacer().overlay(
                      List {
                          Text("Hello World!").font(.title2)
                              .listRowBackground(Color.clear)
                          Text("Hello World again").font(.title2)
                              .listRowBackground(Color.clear)
                      }.onAppear() {
                          UITableView.appearance().backgroundColor = UIColor.green
                          UITableViewCell.appearance().backgroundColor = UIColor.green
                      }
                  )
              }
          }
          

          【讨论】:

            【解决方案17】:

            更改背景颜色

            正如其他人所提到的,更改 UITableView 背景会影响您应用中的所有其他列表。

            但是,如果您想要不同的背景颜色,您可以将默认设置为 clear,并在 swiftui 视图中设置背景颜色,如下所示:

            List {
                Text("Item 1")
                Text("Item 2")
                Text("Item 3")
            }
            // Ignore safe area to take up whole screen
            .background(Color.purple.ignoresSafeArea())
            .onAppear {
                // Set the default to clear
                UITableView.appearance().backgroundColor = .clear
            }
            

            您可能希望更早地设置 tableview 外观,例如在 SceneDelegate 或根视图中,如下所示:

            // SceneDelegate
            func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
                  
                
                guard let windowScene = scene as? UIWindowScene else {
                    print("Returning because screne does not exist")
                    return
                        
                }
                
                // Set here    
                UITableView.appearance().backgroundColor = .clear
                let contentView = ContentView()
                let window = UIWindow(windowScene: windowScene)
                window.rootViewController = UIHostingController(rootView: contentView)
                self.window = window
                window.makeKeyAndVisible()
            }
            
            
            // Root App View
            @main
            struct ListBackgroundApp: App {
                
                init() {
                    UITableView.appearance().backgroundColor = .clear
                }
                
                var body: some Scene {
                    WindowGroup {
                        ContentView()
                    }
                }
            }
            

            【讨论】:

              【解决方案18】:

              MacOS 解决方案

              以下代码使所有Lists 背景颜色透明:

              // Removes background from List in SwiftUI
              extension NSTableView {
                  open override func viewDidMoveToWindow() {
                      super.viewDidMoveToWindow()
                      
                      backgroundColor = NSColor.clear
                      if let esv = enclosingScrollView {
                          esv.drawsBackground = false
                      }
                  }
              }
              

              以下代码使所有TextEditors 背景颜色透明:

              extension NSTextView {
                  open override var frame: CGRect {
                      didSet {
                          backgroundColor = .clear
                          drawsBackground = true
                      }
                  }
              }
              

              【讨论】:

                【解决方案19】:

                https://stackoverflow.com/a/59970379/9439097 的答案似乎是迄今为止最好的实现。这是一个示例视图:

                import SwiftUI
                
                struct TestView1: View {
                    
                    init(){
                        UITableView.appearance().backgroundColor = UIColor(Color.clear)
                    }
                    
                    @State var data = ["abc", "def"]
                    
                    var body: some View {
                        VStack {
                            List {
                                ForEach(data, id: \.self) {element in
                                    Text("\(String(describing: element))")
                                }
                                .background(Color.green)
                                .listRowBackground(Color.blue)
                                
                            }
                            .background(Color.yellow)
                            Spacer()
                            Color.red
                        }
                    }
                }
                
                struct TestView1_Previews: PreviewProvider {
                    static var previews: some View {
                        TestView1()
                    }
                }
                

                产生:

                【讨论】:

                  【解决方案20】:

                  如果您想避免全局设置所有表格视图的外观,可以将UITableView.appearance(whenContainedInInstancesOf:)UIHostingController 结合使用。感谢DanSkeel 您在上面留下的评论指出了这一点。我是这样使用的:

                  public class ClearTableViewHostingController<Content>: UIHostingController<Content> where Content: View {
                      public override func viewDidLoad() {
                          UITableView.appearance(whenContainedInInstancesOf: [ClearTableViewHostingController<Content>.self]).backgroundColor = .clear
                      }
                  }
                  

                  你可以像这样使用ClearTableViewHostingController

                  let view = MyListView()
                  let viewController = ClearTableViewHostingController(coder: coder, rootView: view)
                  

                  然后在您的视图中,您可以像这样设置列表背景颜色:

                  List {
                      Text("Hello World")
                  }
                  .background(Color.gray)
                  

                  【讨论】:

                    【解决方案21】:

                    只需在init()方法中添加UITableView外观背景颜色并添加列表样式(.listStyle(SidebarListStyle())。不要忘记导入UIKit 模块

                    struct HomeScreen: View {
                    init() {
                        UITableView.appearance().backgroundColor = .clear
                    }
                    
                    let tempData:[TempData] = [TempData( name: "abc"),
                                             TempData( name: "abc"),
                                             TempData( name: "abc"),
                                             TempData( name: "abc")]
                    
                    var body: some View {
                        ZStack {
                            Image("loginBackgound")
                                .resizable()
                                .scaledToFill()
                            List{
                                ForEach(tempData){ data in
                                    Text(data.name)
                                }
                            }
                            .listStyle(SidebarListStyle())
                            
                        }
                        .ignoresSafeArea(edges: .all)
                    }
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 2022-01-03
                      • 2021-09-22
                      • 2020-05-15
                      • 1970-01-01
                      • 2021-02-11
                      • 2020-01-01
                      • 2022-08-12
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多