12

Trying to make a custom list using a view as the list row style (to get rid of the ugly line separates in the list by default).

However, once I put my ZStack rows inside a scroll view, the scroll view scrolls in both directions and not just vertically.

Here is the contentView:

NavigationView {
            ScrollView{
                VStack(alignment: .leading){
                    ForEach(friends) { friends in
                        NavigationButton(destination: MessageDetailView(friend: friends)) {
                            CustomListItem(friend: friends)
                        }
                    }
                    Spacer()
                }
            }
                .foregroundColor(.black)
                .navigationBarTitle(Text("Messages"))
        }

and here is the customListItem:

Group{
            ZStack {
                RoundedRectangle(cornerRadius: 10)
                    .shadow(radius: 1, y:1)
                    .frame(width: UIScreen.main.bounds.width - 32, height: 75)
                    .foregroundColor(.gray)

                HStack {
                    Image(systemName: "person.crop.circle")
                        .resizable()
                        .frame(width: 50, height: 50)
                    VStack(alignment: .leading) {
                        HStack {
                            Text(friend.name)
                                .font(.headline)
                            Text("\(friend.date, formatter: dateFormatter)")
                        }
                        Text(friend.messagesReceived[0])
                            .font(.subheadline)
                        }       .lineLimit(nil)
                    Spacer()
                    Image(systemName: "chevron.right.circle")
                        .foregroundColor(.black)
                    }.padding(10)
                }.padding([.leading, .trailing])
        }

Is there any way I can limit the scrolling to vertical or force a frame on this?

Trying to use the .frame(...) modifier does not work as I've tried it. This results in the view not loading at all.

Example Images:

Without ScrollView

With ScrollView wrapping the VStack

5 Answers 5

21

As of Xcode 11 beta 3 (11M362v) there is an axes parameter when constructing a ScrollView which can be set to .horizontal or .vertical

ScrollView(.vertical, showsIndicators: true) { ... }
Sign up to request clarification or add additional context in comments.

1 Comment

This should be the accepted answer! Note that even with .vertical added as shown, if the content of the ScrollView is wider than the width of the ScrollView, you can still get some sideways scrolling. Constraining the content width fixes this.
11

This can be achieved with a GeometryReader. Wrap your ScrollView in one and then set the width of your VStack.

GeometryReader is a super easy, and pretty useful trick to have in your belt for SwiftUI :)

Here's how I got it working with your code:

NavigationView {
            GeometryReader { geometry in
                ScrollView {
                    VStack(alignment: .leading){
                        ForEach(self.friends) { friend in
                            NavigationButton(destination: MessageDetailView(friend: friend)) {
                                CustomListItem(friend: friend)
                            }
                        }
                        Spacer()
                    }.frame(width: geometry.size.width)
                }
                    .foregroundColor(.black)
                    .navigationBarTitle(Text("Messages"))
            }
        }

2 Comments

Genius, this worked! Didn't know about GeometryReader -> will look into it! thanks :)
@piebie I knew about GeometryReader but your answer is awesome because it shows how it can be used with VStack and Scrollview to great effect. In my case, the layout broke on rotation and now it works like a champ thanks to you.
6

Using iOS 14, Swift 5, SwiftUI 2.0

This is the answer... you can use both vertical and horizontal in a set.

ScrollView([.vertical,.horizontal]) {
  ....
}

Comments

1

Although in most cases the above answers works but none of them did work for me!

In my case, the problem was the scrollView children which were wider than the scrollView!

adding a static width to them did the trick.

Comments

0

Try being more specific with the scroll direction like this

ScrollView(.vertical) {}

1 Comment

Welcome to StackOverflow! It looks like this answer doesn't really add anything more than this answer does; without some more content to differentiate your answer from the linked one, yours will likely be downvoted or removed. Please edit your answer to put some more explanation/content/references in. If you aren't able to, no worries! There are plenty of other questions out there; just remove this post and try again on another question. Happy answering!

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.