1

I have a horizontally scrolling ScrollView in SwiftUI. I need to somehow center the element that is shown more than a half. I can't figure out how to get ScrollView position in percent, and I don't know how to optimize using GeometryReader for all possible devices.

ScrollView(.horizontal, showsIndicators: false) {
  HStack(spacing:10) {
    ForEach (sectionData) { item in
        GeometryReader { geometry in
            SectionView(section: item)
                .rotation3DEffect(
                    Angle(degrees: Double(geometry.frame(in:.global).minX - 30) / -20),
                    axis: (x: 0.0, y: 10.0, z: 0.0))
        }
        .frame(width: 275, height: 275)
    }
  }
  .padding(30)
  .padding(.bottom, 30)
}
.offset(y: -30)
Kai Zheng
  • 6,640
  • 7
  • 43
  • 66
  • did you see ScrollViewReader? [doc](https://developer.apple.com/documentation/swiftui/scrollviewreader) – Simone Pistecchia Mar 16 '21 at 16:31
  • It's not what I need, because I need to somehow read the current position in ScrollView in percents and only then jump to anchor points – Alex Shakalenko Mar 16 '21 at 17:03
  • You could use view preferences to determine the scroll offset and then divide it by your `ScrollView` content height to get a percentage. See https://stackoverflow.com/questions/62588015/swiftui-get-current-scroll-position-from-scrollview for `ScrollView` offset and https://stackoverflow.com/questions/62062839/swiftui-how-to-get-size-height-of-scrollview-content for `ScrollView` content height. – Kai Zheng Mar 17 '21 at 09:00
  • Could you include an image? – mahan Mar 17 '21 at 09:11

1 Answers1

2

This could be an aproach

enter image description here

public struct SectionView: View {
    var section: Int
    
    public var body: some View {
        ZStack {
            Rectangle()
                .frame(width: 275, height: 275, alignment: .center)
            Text("\(section)")
                .foregroundColor(.white)
        }
    }
}
    
public struct ExampleView: View {
    
    
    @State private var isShowingNumber: Int = 0
    
    public var body: some View {
                    
        
        ScrollView(.horizontal, showsIndicators: false) {
            ScrollViewReader { value in
 
                ZStack (alignment: .center) {
                    LazyHStack(alignment: .center, spacing:275) {
                        ForEach (1..<20) { item in

                            Rectangle()
                                .frame(width: 1, height: 1, alignment: .center)
                                .foregroundColor(.clear)
                                .onAppear() {
                                    print(item)
                                    withAnimation() {
                                        value.scrollTo(item, anchor: .center)
                                    }
                                }


                            }
                    }

                    HStack(spacing:10) {
                        ForEach (1..<20) { item in
                            GeometryReader { geometry in
                                ZStack {
                                    SectionView(section: item)
                                        .id(item)
                                        .rotation3DEffect(
                                            Angle(degrees: Double(geometry.frame(in:.global).minX - 30) / -20),
                                        axis: (x: 0.0, y: 10.0, z: 0.0))
                                }
                            }
                            .frame(width: 275, height: 275)
                    }
               }
              .padding(30)
              .padding(.bottom, 30)
                }
            }
            
        }
        .offset(y: -30)
    }
}
Simone Pistecchia
  • 2,746
  • 3
  • 18
  • 30