【问题标题】:SwiftUI: How would I make stretchable (flexible) sticky header?SwiftUI:我将如何制作可拉伸(灵活)的粘性标题?
【发布时间】:2022-08-17 00:53:44
【问题描述】:

好吧,老实说,我做到了,因为我需要它,然后才环顾四周,并没有在 SwiftUI 中找到任何关于 SO native 的东西,所以想分享一下。因此,这只是一个自我回答的问题。

最初,我需要粘性可拉伸粘性标头用于仅依赖于ScrollView 的惰性内容。

后来(在我得到解决方案之后)我找到了this one on Medium,但我不喜欢它(并且至少不推荐),因为:

  1. 过于复杂(许多不需要的代码,许多不需要的计算)
  2. 仅依赖(并连接)安全区域,因此适用性有限
  3. 基于offset(我不喜欢使用offset,因为它与布局不一致等)
  4. 它不具有粘性,要使其具有粘性,还需要更多代码

    所以,实际上所有这些文字只是为了满足 SO 问题的要求 - 谁知道我在这里知道我不喜欢输入很多文字,最好输入代码????,简而言之 - 我的方法如下回答,也许有人觉得它有用。

    SwiftUI 免费提供给我们的初始代码

    ScrollView {
        LazyVStack(spacing: 8, pinnedViews: [.sectionHeaders]) {
            Section {
                ForEach(0...100) {
                    Text(\"Item \\($0)\")
                        .frame(maxWidth: .infinity, minHeight: 60)
                }
            } header: {
               Image(\"picture\").resizable().scaledToFill()
                   .frame(height: 200)
            }
        }
    }
    

    向上滚动时标题是粘性的,但向下滚动时不会(与内容一起拖动),并且它不可拉伸。

    标签: ios swift swiftui


    【解决方案1】:

    iOS 15.5(初始)

    好的,我们需要解决两个问题:

    1. 在向下拖动时将标题顶部固定到ScrollView 的顶部
    2. 向下拖动时拉伸标题以使标题内容(大多数情况下为图像)缩放以填充

      解决此问题的一种可能方法:

      1. ScrollView 现在私下管理内容偏移(UIKit 变体不在此处的主题中),因此使用覆盖固定到顶部
            ScrollView {
                // ...
            }
            .overlay(
                // >> any header
                Image("picture").resizable().scaledToFill()
                // << header end
                    .frame(height: imageHeight)  // will calculate below
                    .clipped()
        
        1. 使用Section 默认标头(作为占位符)计算与ScrollView 顶部的当前距离

           Section(...) {
             // ...
           } header: {
               // here is only caculable part
               GeometryReader {
                   // detect current position of header bottom edge
                   Color.clear.preference(key: ViewOffsetKey.self,
                       value: $0.frame(in: .named("area")).maxY)
               }
               .frame(height: headerHeight)
               .onPreferenceChange(ViewOffsetKey.self) {
                   // prevent image negative height if header is not pinned 
                   // for simplicity (can be optional, etc.)
                   imageHeight = $0 < 0 ? 0.001 : $0
               }
           }
          

        实际上就是这样,其他一切都只是演示部分。

        使用 Xcode 13.4 / iOS 15.5 测试

        Test module is here

    【讨论】:

      猜你喜欢
      • 2019-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-13
      • 1970-01-01
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      相关资源
      最近更新 更多