Rreci Rams
Rreci Rams

Reputation: 71

SwiftUI - Adjust ScrollView scroll indicator insets

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.

Upvotes: 5

Views: 7395

Answers (2)

riccardo
riccardo

Reputation: 299

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

ScrollView {

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

See contentMargins - Documentation

Upvotes: 5

Steve M
Steve M

Reputation: 9784

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.

Upvotes: 11

Related Questions