0

I added .scrollTargetLayout(), and .scrollPosition(id: $scrollID) to my ScrollView, and then used ForEach in ScrollView to generate 12 rectangles, and the isTaped variable will be converted when those rectangles are clicked. There is a Spacer() below that will appear when isTaped is true. But when I click on those rectangles, they change strangely(the id on rectangle isn't the correct), and the scroll id at the top can also be seen. The scroll id is not really changed. I want to ask why this is?

here is preview: The id change weird on Xcode preview, and it also

This is the preview on Simulator

It's preview image

here is my code below:

struct WeirdScrollView: View {
    @State private var isTaped: Bool = false
    @State private var scrollID: Int? = 0
    
    var body: some View {
        VStack {
            VStack {
                Text("scroll id: \(scrollID ?? 0)")
                
                ScrollView(.horizontal, showsIndicators: false) {
                    LazyHStack(alignment: .top) {
                        ForEach(0..<12, id: \.self) { i in
                            RoundedRectangle(cornerRadius: 25)
                                .overlay {
                                    Text("id: \(i)")
                                        .foregroundStyle(Color.white)
                                }
                                .containerRelativeFrame(.horizontal, count: 3, spacing: 10.0)
                                .id(i)
                                .onTapGesture {
                                    withAnimation {
                                        isTaped.toggle()
                                    }
                                }
                        }
                    }
                    .scrollTargetLayout()
                }
                .scrollTargetBehavior(.viewAligned)
                .scrollPosition(id: $scrollID)
                
                if isTaped {
                   Spacer(minLength: 300)
                }
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}

I was originally going to make a custom Date Picker(there is only one Date Picker on screen, and user can scroll it horizontal), but when I did the above things(change isTaped), something weird happened to it. My project need scroll id to binding what rectangle is appear on screen, but when I remove the .scrollPosition(id: $scrollID), and it run very well but not fit what I need

3
  • Difficult to reproduce your problem, but I think I saw it once. Have you tried using HStack instead of LazyHStack? Commented Feb 3, 2024 at 6:25
  • If I use HStack to arrange those rectangles in a row, the scroll id remains unchanged when I scroll the ScrollView. Commented Feb 3, 2024 at 7:28
  • yes you are correct. Try the HStack and removing the .id(i), seems to work for me. Commented Feb 3, 2024 at 7:39

1 Answer 1

0

I've made some changes to your code, referring to rob mayoff's answer here. As he says I use HStack as opposed to LazyHStack. As the picture below indicates, the scroll id text does change. And the ID numbers over the rectangles remain the same. One major changes is such that I have ZStack to encapsulate RoundedRectangle and the ID Text separately.

import SwiftUI

struct WeirdScrollView: View {
    @State private var isTapped: Bool = false
    @State private var scrollID: Int? = 0

    var body: some View {        
        VStack {
            Text("scroll id: \(scrollID ?? 0)")
            ScrollView(.horizontal, showsIndicators: false) {
                HStack {
                    ForEach(0..<12, id: \.self) { i in
                        ZStack {
                            RoundedRectangle(cornerRadius: 25)
                                .frame(maxWidth: .infinity, maxHeight: isTapped ? 300 : .infinity)
                                .containerRelativeFrame(.horizontal, count: 3, spacing: 10.0)
                                .onTapGesture {
                                    withAnimation {
                                        isTapped.toggle()
                                        scrollID = i
                                    }
                                }
                            Text("id: \(i)")
                                .foregroundStyle(Color.white)
                        }
                    }
                }
                .scrollTargetLayout()
            }
            .scrollTargetBehavior(.viewAligned)
            .scrollPosition(id: $scrollID)
        }
    }
}

enter image description here

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

1 Comment

You are welcome. I've realized that I had double VStacks. So I've removed one.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.