Tenho dúvidas sobre a sincronização de posições de exibição durante uma mudança de animação.
Esta é a versão que estou buscando, mas observe que quando o teclado aparece, a altura da visualização muda imediatamente, sem animação.
Esta versão é a que eu tenho atualmente, com a animação quando a altura da visualização diminui, mas observe que, ao deslizar para baixo, há uma lacuna perceptível entre o cabeçalho da data e o topo da visualização de lista. Parece meio quebrado.
Aqui está o código:
.onReceive(keyboardHeightPublisher.removeDuplicates()) { height in
withAnimation {
let unadjustedKeyboardHeight = self.keyboardUnadjustedHeight - height
self.keyboardAdjustedListHeight = unadjustedKeyboardHeight
} completion: {
switch (self.modalState) {
case .didShow:
self.modalState = .didShow
default:
break
}
}
}
Então o self.keyboardAdjustedListHeight
é anexado à visualização de lista:
.frame(height: self.keyboardAdjustedListHeight)
.position(CGPoint(x: (geometry.size.width / 2), y: (self.gesturePosition.y + (self.dateHeaderRect.height / 2)) + (self.keyboardAdjustedListHeight / 2)))
O modal inteiro é apenas
ZStack
- VStack (date header)
- drag gesture
- VStack (list view)
- positioned under the date header based on drag gesture position.
Eu tentei matchedGeometryEffect
, mas não adiantou.
Alguma pista?
EDIT: Estou tentando obter o segundo GIF (visualização de lista animada), mas o único problema é o espaço ao arrastar para baixo.
SOLUÇÃO: Usei uma variação da solução de @Benzy Neez aqui.
Este era o efeito pretendido. Basicamente, uma animação da visualização de lista encolhendo, mas sem separação do cabeçalho de data da visualização de lista ao arrastar para baixo. Este código está abaixo do VStack da visualização de lista. Então, ainda assim:
ZStack
VStack (date view)
(drag gesture updates position)
VStack (list view)
(updates position based on drag gesture)
.animation(.easeInOut, value: self.animateShrinkModal)
.toolbar(content: {
ToolbarItem(placement: .keyboard) {
EmptyView()
}
})
.onReceive(keyboardHeightPublisher.removeDuplicates()) { height in
let unadjustedKeyboardHeight = self.keyboardUnadjustedHeight - height
self.keyboardAdjustedListHeight = unadjustedKeyboardHeight
if height > .zero {
self.animateShrinkModal.toggle()
}
switch (self.modalState) {
case .didShow:
self.modalState = .didShow
default:
break
}
}
Como você pode ver, eu só aciono a animação quando a altura do teclado não é zero. A altura modal é redefinida sem animação logo após a altura do teclado ser zerada, o que ocorre bem depois do término do processo de arrastar. Mesmo arrastar lentamente em direção ao teclado produz o efeito desejado.