【问题标题】:Swiftui Scrollview scroll to bottom of listSwiftui Scrollview 滚动到列表底部
【发布时间】:2020-11-19 23:10:35
【问题描述】:

每次添加新项目时,我都会尝试让视图滚动到项目列表的底部。 这是我的代码,有人可以帮忙吗?

ScrollView(.vertical, showsIndicators: false) {
                ScrollViewReader{ value in
                    VStack() {
                        ForEach(0..<self.count, id:\.self) {
                            Text("item \($0)")
                        }
                    }.onChange(of: self.data.sampleCount, perform: value.scrollTo(-1))
                }
            }

【问题讨论】:

    标签: swift swiftui scrollview


    【解决方案1】:

    我们需要为ScrollView 中我们想要滚动到的视图提供id

    这是一个解决方案的演示。使用 Xcode 12.1 / iOS 14.1 测试

    struct DemoView: View {
        
        @State private var data = [String]()
    
        var body: some View {
            VStack {
                Button("Add") { data.append("Data \(data.count + 1)")}
                    .padding().border(Color.blue)
                    
                ScrollView(.vertical, showsIndicators: false) {
                    ScrollViewReader{ sr in
                        VStack {
                            ForEach(self.data.indices, id:\.self) {
                                Text("item \($0)")
                                    .padding().id($0)     // << give id
                            }
                        }.onChange(of: self.data.count) { count in
                            withAnimation {
                                sr.scrollTo(count - 1)   // << scroll to view with id
                            }
                        }
                    }
                }
            }
        }
    }
    

    【讨论】:

    • ios13怎么样?
    【解决方案2】:

    您可以在列表底部添加一个 EmptyView 项

    ScrollView(.vertical, showsIndicators: false) {
                ScrollViewReader{ value in
                    VStack() {
                        ForEach(0..<self.count, id:\.self) {
                            Text("item \($0)")
                        }
                        Spacer()
                            .id("anID") //You can use any type of value 
                    }.onChange(of: self.data.sampleCount, perform: { count in
                       value.scrollTo("anID")
                })
            }
    

    【讨论】:

      【解决方案3】:

      这是我的示例/解决方案。

      var scrollView : some View {
           ScrollView(.vertical) {
             ScrollViewReader { scrollView in
               ForEach(self.messagesStore.messages) { msg in
                 VStack {
                   OutgoingPlainMessageView() {
                     Text(msg.message).padding(.all, 20)
                       .foregroundColor(Color.textColorPrimary)
                       .background(Color.colorPrimary)
                   }.listRowBackground(Color.backgroundColorList)
                   Spacer()
                 }
                 // 1. First important thing is to use .id 
                 //as identity of the view
                 .id(msg.id)
                 .padding(.leading, 10).padding(.trailing, 10)
          }
          // 2. Second important thing is that we are going to implement //onChange closure for scrollTarget change, 
          //and scroll to last message id
          .onChange(of: scrollTarget) { target in
              withAnimation {
                  scrollView.scrollTo(target, anchor: .bottom)
              }
          }
          // 3. Third important thing is that we are going to implement //onChange closure for keyboardHeight change, and scroll to same //scrollTarget to bottom.
          .onChange(of: keyboardHeight){ target in
             if(nil != scrollTarget){
             withAnimation {
             scrollView.scrollTo(scrollTarget, anchor: .bottom)
             }
            }
          }
          //4. Last thing is to add onReceive clojure, that will add an action to perform when this ScrollView detects data emitted by the given publisher, in our case messages array.
          // This is the place where our scrollTarget is updating.
          .onReceive(self.messagesStore.$messages) { messages in
              scrollView.scrollTo(messages.last!.id, anchor: .bottom)
              self.scrollTarget = messages.last!.id
             }
            }
           }
          }
      

      还可以看看我在 medium 上的文章。

      https://mehobega.medium.com/auto-scrollview-using-swiftui-and-combine-framework-b3e40bb1a99f

      【讨论】:

        猜你喜欢
        • 2020-02-11
        • 1970-01-01
        • 2020-01-19
        • 2013-02-14
        • 1970-01-01
        • 1970-01-01
        • 2011-02-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多