代码之家  ›  专栏  ›  技术社区  ›  Nicolas Gimelli

SwiftUI-点击时如何在水平滚动视图中居中显示组件?

  •  0
  • Nicolas Gimelli  · 技术社区  · 4 年前

    我有一个水平滚动视图,其中有一个HStack。它包含多个子视图,由ForEach渲染。我希望这样,当这些子视图被点击时,它们在视图中垂直居中。例如,我有:

    ScrollView(.horizontal) {
      HStack(alignment: .center) {
        Circle() // for demonstration purposes, let's say the subviews are circles
          .frame(width: 50, height: 50)
        Circle()
          .frame(width: 50, height: 50)
        Circle()
          .frame(width: 50, height: 50)
        
      }
      .frame(width: UIScreen.main.bounds.size.width, alignment: .center)
    }
    

    我试过这个密码:

    ScrollViewReader { scrollProxy in
        ScrollView(.horizontal) {
          HStack(alignment: .center) {
          Circle()
            .frame(width: 50, height: 50)
            .id("someID3")
            .frame(width: 50, height: 50)
            .onTapGesture {
               scrollProxy.scrollTo(item.id, anchor: .center)
            }
          Circle()
            .frame(width: 50, height: 50)
                .id("someID3")
                .frame(width: 50, height: 50)
                .onTapGesture {
                  scrollProxy.scrollTo(item.id, anchor: .center)
                }
    
    
               ...
            
          }
        }
    

    但它似乎没有效果。有人知道我该怎么做吗?

    0 回复  |  直到 4 年前
        1
  •  0
  •   Denzel    4 年前

    创建了一个自定义滚动堆栈,并使用几何体读取器和一点计算,以下是我们的内容:

    struct ContentView: View {
    
        var body: some View {
            ScrollingHStack(space: 10, height: 50)
        }
        
    }
    
    struct ScrollingHStack: View {
        
        var space: CGFloat
        var height: CGFloat
        var colors: [Color] = [.blue, .green, .yellow]
        
        @State var dragOffset = CGSize.zero
        
        var body: some View {
            GeometryReader { geometry in
            HStack(spacing: space) {
                ForEach(0..<15, id: \.self) { index in
                    
                    Circle()
                        .fill(colors[index % 3])
                        .frame(width: height, height: height)
                        .overlay(Text("\(Int(dragOffset.width))"))
                        .onAppear {
                            dragOffset.width = geometry.size.width / 2  - ((height + space) / 2)
                        }
                        .onTapGesture {
                            let totalItems = height * CGFloat(index)
                            let totalspace = space * CGFloat(index)
                            withAnimation {
                                dragOffset.width = (geometry.size.width / 2) - (totalItems + totalspace) - ((height + space) / 2)
                            }
                        }
                }
            }
            .offset(x: dragOffset.width)
            .gesture(DragGesture()
                        .onChanged({ dragOffset = $0.translation})
            
            )
            }
        }
    }