Saket Kumar
Saket Kumar

Reputation: 1197

Unable to scroll to the bottom of the list implemented with ScrollViewReader in SwiftUI

I am working on a chat app, where I need to categorise the messages based on the date them were exchanged.

View's body looks like below.

@ViewBuilder
private var bodyView: some View {
    ScrollView(.vertical) {
        ScrollViewReader { scrollView in

            LazyVStack {
                ForEach(chatItems, id: \.self) { chatItem in
                    Section(header: Label(chatItem.dateString, font: someFont))
                    {
                        ForEach(chatItem.msgItems) { msgItem in
                            ChatView(data: msgItem)
                        }
                    }
                }
            }
            .onAppear {
               
                if !chatItems.isEmpty {
                    scrollView.scrollTo(chatItems[chatItems.endIndex - 1],
                                        anchor: .bottom)
                }
            }
        }
    }.background(color: someColor)
}

From the code snippet it is cleared that I have sections which shows date, inside the sections I show messages belonging to that date.

My issue: Above code works perfectly I am able to render the view just fine, and it scrolls to the last section as well. What I am not able to achieve is, I want the scrollview to scroll to the end message belonging to last section. But currently it stops at the section, it doesn't go below.

What I have tried.

I tried adding this to the ".onAppear" in inner forEach.

 .onAppear {
        
        scrollView.scrollTo(chatItem.msgItems[chatItem.msgItems.endIndex - 1], anchor: .bottom)
    }
    

It doesn't do anything.

I also tried to force to scroll to the last msg inside last section in outer ".onAppear" that doesn't do anything it doesn't even scroll to the last section, which it normally does with above code.

If help in fixing the issue would be appreciate, also If my question is not clear I am open to edit or explain it further.

Upvotes: 2

Views: 972

Answers (1)

Asperi
Asperi

Reputation: 258541

The scrollTo works by .id, so you have to specify identifier for each view explicitly, like (assuming that msgItem fits this needs, otherwise use corresponding id of your logic):

ForEach(chatItem.msgItems) { msgItem in
    ChatView(data: msgItem).id(msgItem)     // << here !!
}

See for example and details https://stackoverflow.com/a/60855853/12299030.

Upvotes: 2

Related Questions