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.
Você explicou em um comentário que o problema principal é que o fundo está se destacando do cabeçalho durante a animação.
Como solução, pode ser útil aplicar
.geometryGroup()
ao contêiner pai.Na pergunta, você incluiu um trecho que mostra como está definindo a altura e a posição da visualização de lista. Isso não deveria ser necessário, como demonstrado no exemplo simples abaixo. No entanto, se você realmente quiser fazer dessa forma, pode ser útil adicionar algo
alignment: .top
ao.frame
modificador.Você notará que
easeInOut
está sendo usado para a animação, em vez de.spring
. Isso parece ficar mais sincronizado com o movimento do teclado.