【问题标题】:contentInset on SwiftUI's ListSwiftUI 列表中的 contentInset
【发布时间】:2021-01-01 08:17:47
【问题描述】:

有没有办法在 SwiftUI 的 List 上设置 contentInset?我需要调整底部插图以使最后一个项目在底部按钮上方可见。

我目前的解决方案如下

Section(header: Color.clear.frame(height: 64)) { EmptyView() }

但我想知道有没有更好的方法?

【问题讨论】:

标签: swiftui swiftui-list


【解决方案1】:

概述

  • 您可以添加toolbar,这样您就不必担心内容插入。
  • 工具栏将始终保持在顶部,内容将在工具栏下方滚动
  • Inset 会自动处理

截图:

代码:

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                ForEach(0..<100) { index in
                    Text("Item \(index)")
                }
            }
            .toolbar {
                ToolbarItem(placement: .bottomBar) {
                    Button(action: doSomething) {
                        RoundedRectangle(cornerSize: CGSize(width: 8, height: 8))
                            .foregroundColor(.blue)
                            .overlay(alignment: .center) {
                                Text("Button")
                                    .foregroundColor(.white)
                            }
                            .frame(width: 300, height: 48)
                    }
                }
            }
            .navigationTitle("Title")
        }
    }

    private func doSomething() {

    }
}

【讨论】:

    【解决方案2】:

    我对您的问题的解决方案与Asperi 的答案相似,但他的答案不会在视图顶部显示Button,因为Button 位于Form 的最后一节的页脚处。 (如果不滚动到底部,Button 将不可见。)


    struct ContentView: View {
      
      @Environment(\.colorScheme) var colorScheme
      
      let stringArray: [String] = [String](repeating: "Example", count: 30)
      
      var body: some View {
        ZStack(alignment: .bottom) {
          List {
            ForEach(0..<stringArray.count) { stringIndex in
              Section {
                Text(stringArray[stringIndex])
              }
              
              if  stringIndex == stringArray.count - 1 {
                Spacer()
                  .listRowInsets(EdgeInsets())
                  .listRowBackground(
                    colorScheme == .light ?
                      Color(.secondarySystemBackground) :
                      Color(.systemBackground)
                  )
              }
            }
          }
          .listStyle(InsetGroupedListStyle())
          
          Button(action: {}) {
            Label("ADD NEW ITEM", systemImage: "plus")
          }
          .foregroundColor(.white)
          .font(.headline)
          .frame(height: 64)
          .frame(maxWidth: .infinity)
          .background(Color.red)
          .cornerRadius(5)
          .padding(.horizontal)
        }
      }
    }
    

    【讨论】:

    • @LukasHromadnik 这是正确的答案吗?如果可以,您能否将其标记为已接受其他福利?
    【解决方案3】:

    您可以使用.listRowInsets 定义最后一行内容插入。

    下面的示例代码sn-p:

    struct AddButtonInLastSection: View {
        var data = [[1: [1, 2, 3, 4, 5, 6]], [2: [1, 2, 3, 4, 5, 6]], [3: [1, 2, 3, 4, 5, 6]]]
    
        var body: some View {
            VStack {
                List {
                    ForEach(data, id: \.self) { dict in
                        ForEach(0 ..< dict.keys.count) { i in
                            Section(header: Text("Item \(dict.keys[dict.index(dict.startIndex, offsetBy: i)])")
                            ) {
                                ForEach(0 ..< dict.values.count) { j in
                                    ForEach(dict.values[dict.index(dict.startIndex, offsetBy: j)], id: \.self) { k in
                                        if dict.keys[dict.index(dict.startIndex, offsetBy: i)] == 3 {
                                            if k == 6{
                                                Text("Items: \(k) last")
                                                    .listRowInsets(.init(top: 16, leading: 20, bottom: 64, trailing: 0))
                                            }else {
                                                Text("Items: \(k)")
    
                                            }
                   
                                        } else {
                                            Text("Items: \(k)")
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                Button(action: {}) {
                    RoundedRectangle(cornerRadius: 4)
                        .overlay(
                            Label("ADD NEW ITEM", systemImage: "plus")
                                .foregroundColor(.white))
                }
                .foregroundColor(Color.red)
                .font(.headline)
                .frame(height: 64)
                .frame(maxWidth: .infinity)
                .padding(.init(top: 0, leading: 8, bottom: 0, trailing: 8))
            }
        }
    }
    

    【讨论】:

    • 这种方法的问题是,当您允许选择项目时,最后一个项目的选择看起来会比其他选择高
    【解决方案4】:

    试试下面的代码

    .contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 64, right: 0)
    

    【讨论】:

    • 你读过这个问题吗?这是如何在 SwiftUI 视图而不是 UIKit 视图上设置 contentInset。
    【解决方案5】:

    可能的简单解决方案就是使用最后一节的footer

    下面是一个独立的演示(当然,您可以根据需要调整样式)。使用 Xcode 12.4 / iOS 14.4 测试

    struct DemoButtonInLastSection: View {
        let data = Array(repeating: "some", count: 20)
    
        var body: some View {
          Form {
            ForEach(data.indices, id: \.self) { i in
              Section(footer:
                Group {
                    if i == data.count - 1 {
                        Button(action: {}) {
                            RoundedRectangle(cornerRadius: 8)
                                .overlay(
                                  Label("ADD NEW ITEM", systemImage: "plus")
                                   .foregroundColor(.white))
                        }
                        .font(.headline)
                        .frame(height: 64)
                        .frame(maxWidth: .infinity)
                    }
                }
    
            ) {
                Text("Item \(i)")
            }
          }
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      • 2016-12-14
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      相关资源
      最近更新 更多