2

I am building a chat application with SwiftUI. I am fetching my chat list through Firestore and create the scrollview and insert an empty Stack under the messages as an anchorpoint to which the scrollview is scrolling whenever the message count changes, so far everything is working.

I have encountered an issue that whenever the message typed in the message field is multiline it will cover the last chat message rather than having the scrollview move up (like it happens in Whatsapp or iMessage.

VStack {
  ScrollViewReader { scrollViewProxy in
    ScrollView {
      VStack {
        ForEach(messagesManager.messages, id: \.id) { message in
          ZStack {
            MessageBubble(message: message)
          }.id(message.id)
        }

        HStack {
          Spacer()
            .frame(height: 10)
        }.id(ChatView.emptyScrollToString)

      }.onReceive(messagesManager.$count) { _ in
        withAnimation(.easeOut(duration: 0.5)) {
          scrollViewProxy.scrollTo(ChatView.emptyScrollToString, anchor: .bottom)
        }
      }
      .onAppear {
        withAnimation(.easeOut(duration: 0.5)) {
          scrollViewProxy.scrollTo(ChatView.emptyScrollToString, anchor: .bottom)
        }
      }
    }
  }
  MessageField()
}

I have temporarily solved this by using an inverted and flipped List instead of a ScrollView but I'm wondering if there is a way to get this done without the inversions - basically anchor the Scrollview at the bottom of its container no matter what.

Appreciate any ideas!

Sydney_dev
  • 1,448
  • 2
  • 17
  • 24
Casualzach
  • 38
  • 5

1 Answers1

1

You can't anchor it there, but you can use ScrollViewReader to get a proxy that you can use to scroll the ScrollView when the user resizes the window.

var body: some View {
    GeometryReader { proxy in
        ScrollViewReader { scrollView in
            ScrollView(axis) {
              ...
            }
            .onChange(of: proxy.size) { _ in
                scrollView.scrollTo(lastId)
            }
        }
    }
}
stevex
  • 5,589
  • 37
  • 52