有什么技巧可以确保滚动视图的最后选定值以动画居中

问题描述 投票:0回答:1

我在我的滚动视图中做了很多工作。一切都写好了,但有问题。我希望当用户停止滚动时,最后选择的值进入滚动视图的中心,并且所选值不会保留在中心的外部。

//
//  TextView.swift
//  Blood Pressure Tracker
//
//  Created by MacBook on 27/09/2024.
//

import SwiftUI

struct HorizontalPicker<T: Hashable & CustomStringConvertible>: View {
    @Binding var selectedValue: T // Binding for the selected value
    let values: [T]               // The array of values to display
    let itemWidth: CGFloat = 80   // Width of each item

    var body: some View {
        VStack(alignment: .leading, spacing: 30) {
            // Picker label
            VStack {
                Text("Select Value")
                    .fontWeight(.semibold)

                ZStack {
                    Circle()
                        .frame(width: 60)
                        .foregroundColor(.green)

                    ScrollView(.horizontal, showsIndicators: false) {
                        ScrollViewReader { scrollView in
                            HStack(spacing: 20) {
                                // Add padding to ensure centering for the first and last elements
                                Spacer()
                                    .frame(width: (UIScreen.main.bounds.width / 2) - (itemWidth / 2))
                                
                                ForEach(values, id: \.self) { value in
                                    Text("\(value.description)")
                                        .font(.title2)
                                        .fontWeight(.bold)
                                        .padding()
                                        .foregroundColor(selectedValue == value ? .white : .black)
                                        .background(
                                            Circle()
                                                .frame(width: 40, height: 40)
                                                .foregroundColor(selectedValue == value ? .blue : .clear)
                                        )
                                        .background(GeometryReader { geo in
                                            Color.clear
                                                .onChange(of: geo.frame(in: .global).midX) { midX in
                                                    // Calculate screen's center
                                                    let screenCenterX = UIScreen.main.bounds.width / 2
                                                    let distance = abs(midX - screenCenterX)
                                                    let tolerance: CGFloat = 20 // Adjust tolerance as needed
                                                    if distance < tolerance {
                                                        selectedValue = value
                                                    }
                                                }
                                        })
                                        .onTapGesture {
                                            // Scroll to the tapped value and select it
                                            withAnimation {
                                                selectedValue = value
                                                scrollView.scrollTo(value, anchor: .center)
                                            }
                                        }
                                        .id(value) // Assign id for ScrollViewReader
                                }
                                
                                Spacer()
                                    .frame(width: (UIScreen.main.bounds.width / 2) - (itemWidth / 2))
                            }
                            .onAppear {
                                // Scroll to the initially selected value when the view appears
                                DispatchQueue.main.async {
                                    scrollView.scrollTo(selectedValue, anchor: .center)
                                }
                            }
                        }
                    }
                    .frame(height: 100) // Constrain the height of the ScrollView
                }
            }

            Spacer()
            
            // Show selected value
            VStack(alignment: .leading) {
                Text("Selected Value: \(selectedValue.description)")
            }
        }
        .padding()
    }
}

// Preview
struct HorizontalPickerPreview: View {
    @State private var selectedInt = 110
    @State private var selectedString = "Apple"
    @State private var selectedFloat: Float = 5.5

    var body: some View {
        VStack(spacing: 30) {
            // Integer picker
            HorizontalPicker(selectedValue: $selectedInt, values: Array(80...200))
                .frame(height: 150)

            // String picker
            HorizontalPicker(selectedValue: $selectedString, values: ["Apple", "Banana", "Cherry", "Date", "Elderberry"])
                .frame(height: 150)
            
            // Float picker
            HorizontalPicker(selectedValue: $selectedFloat, values: stride(from: 1.0, through: 10.0, by: 0.5).map { Float($0) })
                .frame(height: 150)
        }
    }
}

#Preview {
    HorizontalPickerPreview()
}

这是我的代码。

我也来chatgpt。但我无法成功。我做什么?

swift scrollview
1个回答
0
投票

看看这篇文章/教程。我想这可能正是您正在寻找的Hacking with Swift

具体看scrollTargetLayoutscrollTargetBehavior

© www.soinside.com 2019 - 2024. All rights reserved.