3

I'm trying to make my view scroll to the bottom of the item list every time a new item is added. This is my code, can someone help please?

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))
                }
            }

3 Answers 3

5

You can add an EmptyView item in the bottom of list

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")
            })
        }
Sign up to request clarification or add additional context in comments.

1 Comment

I've used it this way Spacer().id(names.count) so that I can use onChange(of: int) { _ in value.scrollTo(names.count) }
4

We need to give id for views which in ScrollView we want to scroll to.

Here is a demo of solution. Tested with Xcode 12.1 / iOS 14.1

demo

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
                        }
                    }
                }
            }
        }
    }
}

1 Comment

How about ios13?
1

Here is my example/solution.

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
       }
      }
     }
    }

Also take a look at my article on medium.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.