5

I am creating a chat app and I want the content of the ScrollView to go beneath the input field (while scrolling up). I already put the ScrollView and the input field in a ZStack. Bottom padding on the ScrollView puts the content up, but I also want the scroll indicator to move up with the content.

Is there any way to change the insets of the scroll indicator to match the padding, or any other workaround to achieve what I'm looking for?

Here's the current code:

          ZStack(alignment: .bottom) {
            ScrollView {
                ScrollViewReader { value in
                    VStack(spacing: 5) {
                        ForEach(MOCK_MESSAGES) {
                            mMessage in
                            MessageView(mMessage: mMessage)
                        }
                        .onAppear {
                            value.scrollTo(MOCK_MESSAGES.count - 1)
                        }
                    }
                    .padding(.top, 10)
                    .padding(.bottom, 40)
                }
            }
            MessageInputView(messageText: $messageText)
        }

Summing up: The idea is to have the ScrollView to be above the input view, but move the content underneath input view when scrolling up.

4
  • Please upload the code that you have tried so far Commented Jan 21, 2021 at 18:36
  • @LucaSfragara, uploaded. Commented Jan 21, 2021 at 19:21
  • did you find a solution? Commented Aug 19, 2021 at 11:09
  • @sheldor I answered with a couple of solutions Commented Oct 29, 2021 at 23:05

2 Answers 2

11

iOS 15 / Swift 3

You could do this with .safeAreaInset instead of padding, then it handles the scroll indicator insets for you as well.

ScrollView {
    ScrollViewReader { value in
        VStack(spacing: 5) {
            // stuff
        }
    }
}
.safeAreaInset(edge: .bottom) {
    MessageInputView(messageText: $messageText)
}

Note: .safeAreaInsets doesn't seem to be working on List as of Xcode 13.1.

UPDATE: As of iOS 15.2, safeAreaInsets() works with List and Form as well.

iOS 14 / Swift 2 or with List

Like many things in SwiftUI, there doesn't seem to be a to do it without tinkering with the underlying UIKit components. There's an easy solution for this one though, using the Introspect library:

ZStack(alignment: .bottom) {
    ScrollView {
        ScrollViewReader { value in
            VStack(spacing: 5) {
                // stuff
            }
            .padding(.top, 10)
            .padding(.bottom, 40)
        }
    }
    .introspectScrollView { sv in
        sv.verticalScrollIndicatorInsets.top = 10
        sv.verticalScrollIndicatorInsets.bottom = 40
    }
    MessageInputView(messageText: $messageText)
}

You could also do it with a List with introspectTableView.

Sign up to request clarification or add additional context in comments.

1 Comment

Hey @Steve M I do the same but I faced one issue. For example: we have a MessageInputView with dynamic height and when height is increased the ScrollView doesn't scroll up to keep the same content area visible. Do you know to fix/solve this issue? Thanks
6

since iOS 17 there is a modifier for ScrollViews to address this issue:

ScrollView {

}.contentMargins(.top, 100.0, for: .scrollIndicators)

See contentMargins - Documentation

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.