Navegação interativa
interactiveNavigation(frame) adiciona volta pela borda a uma transição personalizada de páginas no iOS. A página acompanha o dedo; soltar antes da metade cancela, enquanto continuar ou lançar o gesto para frente confirma a volta. Uma spring do Jolt preserva a velocidade de soltura e acomoda as páginas. Frame e router só atualizam o histórico quando o UIKit confirma.
Disponível desde a 0.1.0-rc.1. Recompile o app nativo. Integração verificada com NativeScript Core 9.1.3 e vue-router-ns 0.1.0-rc.2.
Um handle por entrada
import { interactiveNavigation } from '@rafaelaugusto/jolt/interactive-navigation'
// O Frame já está carregado. Crie outro handle para cada push.
const motion = interactiveNavigation(frame, {
spring: 'smooth', // ou { duration: 480, bounce: 0 }
onState(event) {
// Eventos de ciclo de vida, nunca um observador por frame.
if (event.outcome === 'cancelled') console.log('Continua nesta página')
},
})
try {
await router.push('/place/cala-serena', { transition: motion.transition })
// Um guard/redirect pode resolver sem usar esta transição.
if (motion.state === 'ready') motion.dispose()
} catch (error) {
motion.dispose()
throw error
}
// A entrada lembra a transição também para a volta programática.
await router.back()Com Core puro, passe transition: motion.transition a frame.navigate({ create: () => page, ... }). Descarte o handle se a navegação nunca começar. Não reutilize a transição em outra entrada. Volta confirmada, remoção do histórico e unload do Frame liberam automaticamente o recognizer e o estado de transição do Core. dispose() é idempotente; na página visível, restaura o gesto padrão do Core conforme page.enableSwipeBackNavigation.
supported é false e transition é undefined no Android ou quando falta a classe nativa compilada. O chamador pode navegar normalmente com essas opções. Esta API não implementa predictive back no Android.
Dedo, spring e histórico
- Um
UIScreenEdgePanGestureRecognizernativo começa na borda inicial (esquerda em LTR, direita em RTL). Exige intenção horizontal, entrada atual com destino de volta e nenhuma transição ativa no UIKit. - O gesto chama uma vez o callback de volta fornecido pelo Core. O delegate existente do controlador de navegação fornece ao UIKit o animador e o controlador interativo do Jolt; o Jolt não substitui nem faz swizzle desse delegate.
- O gesto move as views reais das páginas. Na soltura,
JoltSpringAdvanceroda em um display link nativo, levando a velocidade do dedo à mesma equação das springs dos valores vivos do Jolt. Não há callbacks JS por frame. JS na thread principal ainda pode bloquear o UIKit. - A decisão combina progresso e uma projeção curta da velocidade. Mover de volta à borda pode cancelar mesmo após cruzar a metade. A acomodação tem limite de três segundos reais, inclusive com spring incomum ou
timeScaleglobal lento. - Cancelar restaura as duas transformações e mantém rota e histórico. Confirmar faz uma única volta. Entradas empilhadas têm handles independentes; só a entrada no topo aceita gestos.
spring aceita smooth, snappy, bouncy ou configurações duration/bounce e stiffness/damping/mass. Delay, repeat, tween e velocidade explícita não são aceitos. O progresso acompanha o dedo; timeScale afeta a spring no início de cada navegação. O progresso fica limitado às bordas da página, inclusive com spring elástica.
Guards, acessibilidade e limpeza
page.enableSwipeBackNavigation é sempre respeitado. O vue-router-ns o desabilita enquanto guards assíncronos de saída precisam executar; use o botão de voltar para essa navegação. canBegin() permite uma condição síncrona adicional. Não espera decisões assíncronas.
Redução de movimento desabilita o gesto e conclui imediatamente a animação programática. O botão de voltar permanece disponível. Suspensão, mudança de viewport, cancel() e descarte cancelam um gesto ainda segurado. Depois de o UIKit aceitar a soltura, a limpeza conclui essa decisão sem tentar reverter uma volta confirmada.
state pode ser ready, animating, idle, dragging, finishing, cancelling ou disposed. O evento finishing/cancelling inclui release: { progress, velocity }, com velocidade em larguras de página por segundo. O evento idle após um gesto inclui outcome: 'completed' | 'cancelled'. Erros no observador são informados pelo Trace do NativeScript sem interromper a limpeza.
Mantenha o conteúdo visual da página anterior montado enquanto ela estiver no histórico: a volta interativa mostra essa página antes de navigatedTo. Reconstruir tudo apenas nesse evento deixa a prévia vazia.
Por padrão, esta API anima páginas inteiras do Frame. Para imagem/cartão com o mesmo progresso nativo, use a composição gestos compartilhados. Modais nativos arbitrários, gesto em tela inteira e realização automática de views recicladas continuam fora deste contrato. Ofereça o botão de voltar como alternativa acessível. Veja a validação nativa.