Swiftui программная прокрутка пропускает частые обновления, чтобы получить значениеIOS

Программируем под IOS
Ответить
Anonymous
 Swiftui программная прокрутка пропускает частые обновления, чтобы получить значение

Сообщение Anonymous »

У меня есть следующий код прокрутки скруббера. Проблема заключается в том, что программная прокрутка либо на стартапе («OnPapeAr») не работает, и даже в середине он непредсказуем, где иногда он работает, а иногда нет. Много промахов во время частых обновлений до значения. Я также пытался прокрутить анимацию, без эффекта. Я использую устройство iOS 26 для справки. < /P>
struct VerticalScrubber: View {
var config: ScrubberConfig
@Binding var value: CGFloat

@State private var scrollPosition: Int?

let tickHeight: CGFloat = 8

@State private var isUserInteracting: Bool = false // New state to track user interaction

var body: some View {
GeometryReader { geometry in
let verticalPadding = (geometry.size.height - tickHeight) / 2

ZStack(alignment: .trailing) {
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: config.spacing) {
ForEach(0...(config.steps * config.count), id: \.self) { index in
horizontalTickMark(for: index)
.frame(height: tickHeight)
.id(index)
}
}
.frame(width: 80)
.scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)
.scrollPosition(id: $scrollPosition, anchor: .top)
.contentMargins(.vertical, verticalPadding)
.simultaneousGesture(
DragGesture()
.onChanged { _ in
if !isUserInteracting {
isUserInteracting = true
print("User interaction started")
}
}
.onEnded { _ in
isUserInteracting = false
print("User interaction ended")
}
)

Capsule()
.frame(width: 32, height: 3)
.foregroundColor(.accentColor)
.shadow(color: .accentColor.opacity(0.3), radius: 3, x: 0, y: 1)
}
.frame(width: 100)
.onAppear {
DispatchQueue.main.async {
scrollPosition = Int(value * CGFloat(config.steps))
}
}
.onChange(of: value, { oldValue, newValue in
let newIndex = Int(newValue * CGFloat(config.steps))
print("New index \(newIndex)")
if scrollPosition != newIndex && !isUserInteracting {
scrollPosition = newIndex
print("Position: \(newIndex)")
}
})
.onChange(of: scrollPosition, { oldIndex, newIndex in
guard let pos = newIndex else { return }
let newValue = CGFloat(pos) / CGFloat(config.steps)
if abs(value - newValue) > 0.001 {
if isUserInteracting {
value = newValue
}

}
})
}
}

private func horizontalTickMark(for index: Int) -> some View {
let isMajorTick = index % config.steps == 0
let tickValue = index / config.steps

return HStack(spacing: 8) {
Rectangle()
.fill(isMajorTick ? Color.accentColor : Color.gray.opacity(0.5))
.frame(width: isMajorTick ? 24 : 12, height: isMajorTick ? 2 : 1)

if isMajorTick {
Text("\(tickValue * 5)")
.font(.system(size: 12, weight: .medium))
.foregroundColor(.primary)
.fixedSize()
}
}
.frame(maxWidth: .infinity, alignment: .trailing)
.padding(.trailing, 8)
}
}

#Preview("Vertical Scrubber") {
struct VerticalScrubberPreview: View {
@State private var value: CGFloat = 0
private let config = ScrubberConfig(count: 20, steps: 5, spacing: 8)

var body: some View {
VStack {
Text("Vertical Scrubber (0–100 in steps of 5)")
.font(.title2)
.padding()

HStack(spacing: 30) {
VerticalScrubber(config: config, value: $value)
.frame(width: 120, height: 300)
.background(Color(.systemBackground))
.border(Color.gray.opacity(0.3))

VStack {
Text("Current Value:")
.font(.headline)
Text("\(value * 5, specifier: "%.0f")")
.font(.system(size: 36, weight: .bold))
.padding()

HStack {
Button("−5") {
let newValue = max(0, value - 1)
if value != newValue {
value = newValue
UISelectionFeedbackGenerator().selectionChanged()
}

print("Value \(newValue), \(value)")
}
.disabled(value = CGFloat(config.count))
}
.buttonStyle(.bordered)
}
}

Spacer()
}
.padding()
}
}

return VerticalScrubberPreview()
}


Подробнее здесь: https://stackoverflow.com/questions/797 ... s-to-value
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»