В моем мнении Swiftui я пытаюсь создать складной резюме «сводного» нижнего листа. Чтобы воспроизвести повторную ошибку листов, я добавил перетаскиваемую капсулу и обновил высоту кадра представления на основе перевода. Пока это технически «работает», это безумно нервное и глюко. < /P>
var maxExpandedHeight: CGFloat
@State private var isDragging = false
@State private var isCollapsed = false
@State private var currentHeight: CGFloat = 0
init(transaction: Transaction, maxExpandedHeight: CGFloat = 250) {
self.transaction = transaction
self.maxExpandedHeight = maxExpandedHeight
}
var body: some View {
VStack(spacing: 12) {
// Top grabber handle
Capsule()
.fill(Color.secondary.opacity(isDragging ? 1.0 : 0.4))
.frame(width: 36, height: 5)
.padding(.top, 6)
.accessibilityLabel("Toggle summary details")
.accessibilityAddTraits(.isButton)
.contentShape(.rect)
.onTapGesture {
withAnimation(.spring(response: 0.25, dampingFraction: 0.9)) {
isCollapsed.toggle()
currentHeight = isCollapsed ? 0 : maxExpandedHeight
}
}
.gesture(
DragGesture(minimumDistance: 5)
.onChanged { value in
isDragging = true
// Base value depending on current state
let base = isCollapsed ? 0 : maxExpandedHeight
let proposed = base - value.translation.height
// Clamp to valid range
let clamped = min(max(proposed, 0), maxExpandedHeight)
// Only update if it meaningfully changed to prevent jank
if abs(clamped - currentHeight) > 10 {
withTransaction(SwiftUI.Transaction(animation: .none)) {
currentHeight = clamped
}
}
}
.onEnded { _ in
let shouldCollapse = currentHeight < maxExpandedHeight * 0.5
withAnimation(.spring(response: 0.25, dampingFraction: 0.9)) {
isCollapsed = shouldCollapse
currentHeight = shouldCollapse ? 0 : maxExpandedHeight
isDragging = false
}
}
)
VStack(spacing: 10) {
headerRow
summaryRow(title: "Subtotal", value: transaction.subtotal)
.font(.subheadline)
.foregroundStyle(.secondary)
ScrollView(.vertical) {
VStack {
ForEach(transaction.modifications) { mod in
modificationCard(mod)
.onSwipeToDelete {
deleteMod(mod)
}
.scrollTargetLayout()
}
}
}
.contentMargins(.trailing, 10, for: .scrollContent)
.scrollTargetBehavior(.paging)
.frame(maxHeight: maxExpandedHeight)
Divider().padding(.vertical, 4)
}
.frame(height: currentHeight, alignment: .top)
.animation(.snappy, value: currentHeight)
.clipped()
summaryRow(title: "Total", value: transaction.total())
.font(.title2.bold())
}
.padding()
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 24, style: .continuous))
.overlay(
RoundedRectangle(cornerRadius: 24)
.strokeBorder(.white.opacity(0.1), lineWidth: 1)
)
.shadow(color: .black.opacity(0.1), radius: 10, x: 0, y: 5)
.padding(.horizontal)
.onAppear {
currentHeight = isCollapsed ? 0 : maxExpandedHeight
}
.animation(.spring(response: 0.25, dampingFraction: 0.9, blendDuration: 0.2), value: isCollapsed)
.allowsHitTesting(true)
}
Я пытался добавить анимацию, чтобы сгладить движение, добавил задержки между обновлением перевода перетаскивания, добавил проверку небольших изменений в переводе и т. д., но ничего не помогло. Любая помощь будет оценена по достоинству!
В моем мнении Swiftui я пытаюсь создать складной резюме «сводного» нижнего листа. Чтобы воспроизвести повторную ошибку листов, я добавил перетаскиваемую капсулу и обновил высоту кадра представления на основе перевода. Пока это технически «работает», это безумно нервное и глюко. < /P> [code] var maxExpandedHeight: CGFloat
@State private var isDragging = false
@State private var isCollapsed = false @State private var currentHeight: CGFloat = 0