【问题标题】:SwfitUI List Make Scrolling disabledSwiftUI 列表禁用滚动
【发布时间】:2019-11-13 11:37:35
【问题描述】:

有没有办法让 SwiftUI 中的 List 不可滚动?

像我们一样

tableView.isScrollEnabled

【问题讨论】:

标签: swift swiftui


【解决方案1】:

不要使用可滚动的List,而是使用ForEach

ForEach 默认不可滚动。

这里是一个使用ForEach的例子

struct ContentView: View {
    let colors: [Color] = [.red, .green, .blue]

    var body: some View {
        VStack {
            ForEach(colors, id: \.self) { color in
                Text(color.description.capitalized)
                    .padding()
                    .background(color)
            }
        }
    }
}

ForEach 的一个很好的资源可以在here 上找到,List 的一个很好的资源可以在here 上找到。


更新

目前有两种方法可以阻止List 滚动:

  • 使用UITableView.appearance().isScrollEnabled = false(但这可能会产生意想不到的副作用)
  • 使用第三方依赖Introspect

注意事项

List 包含在 NavigationView

如果您的List 包含在NavigationView 中,那么它仍会滚动。以上两种方法都不能阻止它滚动。

这是一个示例视图:

import SwiftUI
import Introspect

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                ForEach(0..<10, id: \.self) { _ in
                    NavigationLink("Tap") {
                        Text("Hello").onTapGesture {
                            print("hello")
                        }
                    }
                }
            }
//            .onAppear {
//                UIScrollView.appearance().isScrollEnabled = false
//            }
//            .introspectTableView { tableView in
//                tableView.isScrollEnabled = false
//            }
        }
    }
}

取消注释 onAppearintrospectTableView 不会阻止 List 滚动。

List 不包含在 NavigationView

如果List 不包含在NavigationView 中,那么我们可以阻止List 滚动。

如果我们从上面的示例中删除NavigationView,我们可以看到,通过取消注释onAppearintrospectTableViewList 确实会停止滚动。

这里是上述情况的video

【讨论】:

    【解决方案2】:

    这是我的扩展,用于禁用列表上的滚动。

    extension View {
        
        func hasScrollEnabled(_ value: Bool) -> some View {
            self.onAppear {
                UITableView.appearance().isScrollEnabled = value
            }
        }
    }
    

    例子:

    List {
        ...
    }.hasScrollEnabled(false)
    

    【讨论】:

    • 这应该是公认的答案,因为它保留了列表
    • 不幸的是,这似乎也影响了同一 NavigationView 中的其他列表。
    • 这对我不起作用
    【解决方案3】:

    简化 YannSteph 的回答:

    List {
        ...    
    }
    .onAppear {
        UITableView.appearance().isScrollEnabled = false
    }
    

    【讨论】:

    • 这很好用——但是副作用是它适用于 ContentView 中的所有列表。这对我的应用程序来说没问题,但它似乎只会影响你应用它的列表
    • 对我不起作用
    【解决方案4】:

    虽然使用 VStack + ForEach 有点效果,但缺点之一是当点击一行时,点击反馈不再是您对 tableview 的期望(背景不会突出显示),所以它可能不是基于用户体验期望的合适解决方案。

    实现此目的的另一种方法是使用此第三方库:

    https://github.com/siteline/SwiftUI-Introspect

    然后你就可以了

    List {
        // ...
    }
    .introspectTableView { tableView in
                             tableView.isScrollEnabled = false
                         }
    

    【讨论】:

      【解决方案5】:

      如果您需要使用List(例如用于选择),最适合我的方法(而不是禁用所有列表的滚动)是以编程方式设置列表的高度:

      List(items){ item in Text(item.title)}.frame(
        height: CGFloat(items.count) * CGFloat(ROW_HEIGHT)
      )
      

      这样列表将不会滚动,因为它已设置为显示所有项目所需的高度。

      【讨论】:

      • 这很好用,但是,这里的问题是行高。你怎么能得到它?请记住,由于可访问性字体、各种语言等原因,任何固定值都不起作用。
      【解决方案6】:

      不禁用所有列表滚动的最佳方法是:

      List{
       Text("Test")
      }
      .onAppear { UITableView.appearance().isScrollEnabled = false }
      .onDisappear{ UITableView.appearance().isScrollEnabled = true }            
             
      

      【讨论】:

        【解决方案7】:

        我很确定这也会禁用内容,但您可以这样做:

        List {
            // ...
        }.disabled(true)
        

        SwiftUI 中非常缺乏 ScrollView API,因此您可能需要使用 UIViewRepresentable

        【讨论】:

        • 不,这也会禁用列表上的操作,我不想只滚动应该被禁用
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-24
        • 2019-12-07
        • 2020-05-09
        • 1970-01-01
        • 1970-01-01
        • 2020-01-19
        相关资源
        最近更新 更多