4

Is there a way to build UI elements in SwiftUI inside scroll view with bottom Alignment?

My use case: I have a screen where the screen has

  1. Spacer (What ever is left after allocating below elements)
  2. LogoView
  3. Spacer() - 30
  4. Some Text - 4/5 lines
  5. Spacer() - 50 (this will be calculated off of GR size Height)
  6. HStack with Two Button - This should be pinned to bottom of view / ScrollView

I would like to know how Can I pin the HStack view to ScrollView Bottom

I've replicated my setup and reproduced my problems in a Swift playground like so

struct ContentView: View {
        var body: some View {
        GeometryReader { gr in
            ScrollView {
                VStack {
                    Spacer()
                    Image(systemName: "applelogo")
                        .resizable()
                        .frame(width: gr.size.width * 0.5, height: gr.size.height * 0.3, alignment: .center)
                    Spacer().padding(.bottom, gr.size.height * 0.01)
                    Text("SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME")
                        .fontWeight(.regular)
                        .foregroundColor(.green)
                        .multilineTextAlignment(.center)
                        .padding(.top, gr.size.height * 0.05)
                        .padding(.horizontal, 40)
                        .layoutPriority(1)
                    Spacer()
                        .frame(minHeight: gr.size.height * 0.12)
                    HStack {
                        Button(action: {

                        }, label: {
                            Text("Button 1")
                        })
                        .foregroundColor(Color.white)
                        .padding(.vertical)
                        .frame(minWidth: 0, maxWidth: .infinity)
                        .background(Color.blue)
                        .cornerRadius(8)

                        Button(action: {

                        }, label: {
                            Text("Button 2")
                        })
                        .foregroundColor(Color.white)
                        .padding(.vertical)
                        .frame(minWidth: 0, maxWidth: .infinity)
                        .background(Color.blue)
                        .cornerRadius(8)
                    }
                    .padding(.horizontal, 20)
                }
                //.frame(maxWidth: .infinity, maxHeight: .infinity)
            }
        }
    }
}

enter image description here

I understand that when scrollView is introduced in SwiftUI view Spacer length is changed to Zero, Would like to know what's the best way to achieve this

6
  • Can you upload an image or a sketch of your intent UI? Commented Dec 20, 2020 at 21:29
  • @HarshilPatel Please find the updated description above (hope it helps). I want the buttons to pin from bottom of view (aka Scroll View) Commented Dec 21, 2020 at 0:30
  • Does this answer your question stackoverflow.com/a/58708206/12299030? Commented Dec 21, 2020 at 4:59
  • @Asperi, No. I am not looking to customize scrollView behavior, was looking for approach of how to pin views to scrollView bottom (similar to storyboard bottom constraint). Commented Dec 21, 2020 at 5:54
  • Approach is to have a spacer above your button. The height of this spacer needs to be computed based on scroll view height - (content of scroll view). Then this needs to be passed on up the view hierarchy using PreferenceKey and then use it to set the spacer height Commented Dec 21, 2020 at 7:10

2 Answers 2

13
struct SampleView: View {
    var body: some View {
        GeometryReader { gr in
            VStack {
                ScrollView {
                    VStack {

                        // Fills whatever space is left
                        Rectangle()
                            .foregroundColor(.clear)

                        Image(systemName: "applelogo")
                            .resizable()
                            .frame(width: gr.size.width * 0.5, height: gr.size.height * 0.3, alignment: .center)
                            .padding(.bottom, gr.size.height * 0.06)


                        Text("SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME TEXT SOME")
                            .fontWeight(.regular)
                            .foregroundColor(.green)
                            .multilineTextAlignment(.center)
                            .padding(.horizontal, 40)
                            .layoutPriority(1)


                        // Fills 12 %
                        Rectangle()
                            .frame(height: gr.size.height * 0.12)
                            .foregroundColor(.clear)

                        HStack {

                            Button(action: {
                            }, label: {
                                Text("Button 1")
                            })
                            .foregroundColor(Color.white)
                            .padding(.vertical)
                            .frame(minWidth: 0, maxWidth: .infinity)
                            .background(Color.blue)
                            .cornerRadius(8)

                            Button(action: {
                            }, label: {
                                Text("Button 2")
                            })
                            .foregroundColor(Color.white)
                            .padding(.vertical)
                            .frame(minWidth: 0, maxWidth: .infinity)
                            .background(Color.blue)
                            .cornerRadius(8)
                        }
                        .padding(.horizontal, 20)
                        .padding(.bottom, 20)

                    }

                    // Makes the content stretch to fill the whole scroll view, but won't be limited (it can grow beyond if needed)
                    .frame(minHeight: gr.size.height)
                }
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

2

I wanted the scrollview to appear bottom to top instead of top to bottom. This had my answer: https://www.thirdrocktechkno.com/blog/implementing-reversed-scrolling-behaviour-in-swiftui/

TLDR: .rotationEffect(Angle(degrees: 180)).scaleEffect(x: -1.0, y: 1.0, anchor: .center) on the scrollview AND on the items in the scrollview

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.