【问题标题】:Swiftui List Row Cells set padding after View appearsSwiftui List Row Cells 在 View 出现后设置填充
【发布时间】:2019-10-21 12:22:16
【问题描述】:

我有一个标准列表,只有一个文本,右侧有导航箭头。但是在列表加载并出现在屏幕上之后,列表添加了单元格,我认为它们在左侧和右侧添加了填充。但这看起来不太好,所以看起来列表滞后了!

List {
                       ForEach(0..<book.chapters) { index in
                           NavigationLink(destination: ReadingView(book: self.book, chapter: index)){
                               Text("Kapitel \(index + 1)")
                           }
                       }
        }


           .navigationBarTitle(Text(book.long_name), displayMode: .inline)

【问题讨论】:

  • 这几乎可以肯定是一个错误。 SwiftUI 还是新的,我注意到一些类似 List、Form 等的小东西。最好的办法是与 Apple 的文件反馈:feedbackassistant.apple.com
  • 我认为这与在列表中使用 ForEach 有关。当我创建一个静态列表时,这不会发生,但是当我使用 ForEach 循环数据时它会发生。
  • 希望它会尽快修复。我试过禁用填充和其他一切,它似乎仍然存在。我会再次在这里签到。

标签: ios swift swiftui ios13 swiftui-list


【解决方案1】:

我有同样的问题,但只在模拟器上。当我在任何一部手机上运行该应用程序时,无论其年代久远,它都能如预期的那样完美运行。 你应该试试。

编辑:啊,现在我看到了移动数据,你在手机上。在这种情况下,您可以向 Apple 提交错误报告并等待并始终使用最新的软件。

【讨论】:

    【解决方案2】:

    我想出了一个解决方法来解决这个问题。需要注意的是,虽然它修复了表格中的变化,但它会在导航栏标题动画中引入延迟,因此会警告您。

    在 Apple 修复 SwiftUI 的 List 对象之前,您可以同时使用 UIKit 的 TableViewController。

    总而言之,您需要创建一个 TableViewController 并将其包装在 UIViewControllerRepresentable 中,然后将其注入到您的 SwiftUI 视图中。导航操作最好通过 didSelectRowAt 委托方法完成。

    更新:似乎问题已在最新的 XCode 11.4 中解决(但现在模拟器环境中存在更多问题)

    我这里有完整的代码:https://gist.github.com/Rep0se/97d7a97cfd05f42aa597904e6a2cfd3d

    //
    //  UIKitSwiftUITableView.swift
    //  Table Test
    //
    //  Created on 2020-02-19.
    //  Note: While this solution fixes Table shifting bug, it introduces Navigation Bar Title bug for a Large Title. Beware.
    //  LBTATools can be downloaded using Swift Package Manager from: https://github.com/bhlvoong/LBTATools
    //
    
    import SwiftUI
    import LBTATools
    
    struct UIKitSwiftUITableView: View {
        var body: some View {
            NavigationView {
                UIKitSwiftUIContainer()
            }
        }
    }
    
    struct Restaurante: Hashable {
        let name: String
        let image: String
    }
    
    struct UIKitSwiftUIContainer: View {
        let restaurants = [
            Restaurante(name: "Joe's Original", image: "house"),
            Restaurante(name: "Pheasant Plucker", image: "house.fill"),
            Restaurante(name: "Radius", image: "music.house"),
            Restaurante(name: "The Ship", image: "music.house.fill")
        ]
        var body: some View {
            UIKitTableViewRepresentable(restaurants: restaurants)
                .navigationBarTitle("Select a restaurant") // <- UI bug exests for Navigation Bar Title
                .edgesIgnoringSafeArea(.all)
        }
    }
    
    struct UIKitTableViewRepresentable: UIViewControllerRepresentable {
        typealias UIViewControllerType = UIViewController
    
        let restaurants: [Restaurante]
        init(restaurants: [Restaurante]) {
            self.restaurants = restaurants
        }
    
        func makeUIViewController(context: UIViewControllerRepresentableContext<UIKitTableViewRepresentable>) -> UIViewController {
            UIKitComboTableViewController(restaurants: restaurants)
        }
    
        func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<UIKitTableViewRepresentable>) {
    
        }
    }
    
    class UIKitComboTableViewController: UITableViewController {
    
        let reuseIdentifier = "reuseIdentifier"
        var restaurants: [Restaurante]
        init(restaurants: [Restaurante]) {
            self.restaurants = restaurants
            super.init(style: .insetGrouped)
        }
    
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            tableView.register(TableCell.self, forCellReuseIdentifier: reuseIdentifier)
        }
    
        // MARK: - Table view data source
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            // #warning Incomplete implementation, return the number of rows
            return restaurants.count
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            if let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as? TableCell {
                cell.viewModel.name = restaurants[indexPath.row].name
                cell.viewModel.image = restaurants[indexPath.row].image
                cell.accessoryType = .disclosureIndicator
                return cell
            } else {
                return UITableViewCell()
            }
        }
        override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            let hostingController = UIHostingController(rootView: UIKitSwiftUIContainer())
            show(hostingController, sender: self)
        }
    }
    
    class TableCell: UITableViewCell {
        let viewModel = RestaurantViewModel()
        lazy var row = ListRowView(viewModel: viewModel)
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
    
            let hostingController = UIHostingController(rootView: row)
            addSubview(hostingController.view)
            hostingController.view.fillSuperview()
        }
    
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    
    struct ListRowView: View {
        @ObservedObject var viewModel: RestaurantViewModel
        var body: some View {
            HStack{
                Image("Avatar").renderingMode(.original).padding()
                Text(viewModel.name)
                    .foregroundColor(.black)
                Spacer()
            }.frame(minHeight: 44)
        }
    }
    
    class RestaurantViewModel: ObservableObject {
        @Published var name = ""
        @Published var image = ""
    }
    
    struct UIKitSwiftUITableView_Previews: PreviewProvider {
        static var previews: some View {
            UIKitSwiftUITableView()
        }
    }
    

    【讨论】:

      【解决方案3】:

      编辑:iOS 13.6 修复了这个问题,我从那时开始的解决方案现在产生了一个小故障,而不是修复它!

      有一个潜在的解决方法会产生其他并发症:

      动画。 这个奇怪的错误是受动画影响的,所以给它一个像

      这样的动画
      List {
                         ForEach(0..<book.chapters) { index in
                             NavigationLink(destination: ReadingView(book: self.book, chapter: index)){
                                 Text("Kapitel \(index + 1)")
                             }
                         }
          }.animation(.easeInOut(duration: 500))
      
      
             .navigationBarTitle(Text(book.long_name), displayMode: .inline)
      

      至少会使 bug 不可见,但请注意,所有子视图都将继承该动画,因此您需要手动为它们再次覆盖它。如果您正在编写专业应用程序,请使用 Repose 答案中的 TableView 修复。

      奇怪的事情:我们发现它发生在 iPhone XR 和 11(模拟器和真实设备)上,但不在 iPhone 11 Pro 上,所以它可能只发生在 LCD 设备上???

      我希望这可以帮助这个帖子的未来访问者,就像我在遇到那个错误时一样偶然发现这个帖子

      【讨论】:

        【解决方案4】:
        List
        {
           ForEach(items)
           {(item) in
              NavigationLink(destination:Destination())
              {
               Text("example")
              }
           }
        }.listStyle(InsetListStyle())
        

        .listStyle(InsetListStyle()) 帮助我解决了 XCode12 中的问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-01-04
          • 1970-01-01
          • 2020-11-11
          • 1970-01-01
          • 2021-04-24
          • 1970-01-01
          相关资源
          最近更新 更多