Como interpretar o arrastar do dedo no Swift e SwiftUI
Como utilizar o DragGesture do SwiftUI
Thierri Cegantin
Criado à 4 meses atrás
No desenvolvimento do seu aplicativo é bem provável que você queira interpretar os gestos que seu usuário faz com o dedo na tela. Felizmente o SwiftUI tem ferramentas que tornam esse processo bem simples.
É possível com muita facilidade implementar e interpretar os seguintes gestos:
- DragGesture: gesto de arrastar um dedo na tela.
- TapGesture: gesto de "clicar" com o dedo um elemento na tela.
- MagnifyGesture: gesto de pinça, onde o usuário que "aumentar", dar um zoom, em um elemento com dois dedos.
- OnLongPressGesture: gesto de "clicar" por um tempo longo em um elemento na tela.
- RotateGesture: semelhante ao "MagnifyGesture", porém com o intuito de girar o elemento. O usuário usa dois dedos na tela e rotaciona o elemento.
Exemplo de uso do DragGesture
Para demonstrar o uso do DragGesture no desenvolvimento de um aplicativo iOS, vou criar uma View bem simples com um retangulo com bordas arredondas.
import SwiftUI
struct ContentView: View {
var body: some View {
Spacer()
RoundedRectangle(cornerRadius: 10)
.foregroundStyle(.blue)
.frame(width: 300, height: 200)
}
}
Nada de especial foi feito. Apenas o deslocamento do retângulo para a parte inferior da tela através do uso do Spacer() .
Para utilizar o DragGesture, a ideia é que o retângulo fique parcialmente fora da tela, exibindo apenas uma parte de cima. Quando o usuário arrastar o retângulo para cima, ele deverá se revelar completamente.
Para esconder o retângulo fora da tela, vou utilizar a propriedade offset que causa um deslocamento do elemento. No nosso caso será um descolamento no eixo Y (vertical). O valor desse deslocamento será armazenado em uma nova variável dinâmica nomeada deslocamentoVertical.
Note que as coordenadas do eixo Y (vertical) no SwiftUI são organizadas da seguinte forma: o centro é representado pelo valor zero, enquanto os valores negativos correspondem à área acima do centro e os valores positivos se referem à parte abaixo dele.
import SwiftUI
struct ContentView: View {
// desloca 200 unidades para baixo do ponto inicial
@State var deslocamentoVertical : CGFloat = 200
var body: some View {
Spacer()
RoundedRectangle(cornerRadius: 10)
.foregroundStyle(.blue)
.frame(width: 300, height: 200)
.offset(y: deslocamentoVertical)
}
}
Agora vamos implementar um gesto que permitirá que o usuário arraste esse retângulo para cima. Para isso eu vou usar a propriedade gesture. Dentro dela vou usar o método DragGesture que, por sua vez, tem dois métodos disponíveis: onChanged e onEnded.
.gesture(
DragGesture()
.onChanged { value in
// Executado durante o gesto de arrasto
}
.onEnded { value in
// Executado quando o usuário termina o gesto.
// Quando ele tira o dedo da tela.
}
)
Como descrito no código acima oonChanged é o trecho de código que é executado durante o gesto de arrasto do usuário enquanto ele está com o dedo encostado na tela. Esse método recebe um parâmetro que contém todas as informações de localização e deslocamento do dedo do usuário na tela.
Usaremos esse parâmetro para mover o retângulo para cima, alterando o valor da variável deslocamentoVertical. Especificamente, utilizaremos o atributo y da propriedade location, que representa a localização no eixo Y (eixo vertical) do dedo do usuário na tela.
Para tornar o movimento mais fluído vou encapsular esse trecho de código com o método withAnimation. Conheça mais sobre animações neste artigo: Animações no SwiftUI .
.gesture(
DragGesture()
.onChanged { value in
// Executado durante o gesto de arrasto
withAnimation{
deslocamentoVertical = value.location.y
}
}
.onEnded { value in
// Executado quando o usuário termina o gesto.
// Quando ele tira o dedo da tela.
}
)
Note que o código pode ser interpretado da seguinte maneira:
- Quando o usuário começa o gesto de arrastar o elemento Retângulo um trecho de código é executado.
- Neste trecho alteramos o valor da variável deslocamentoVertical (equivalente ao offset do retângulo) para o valor da localização do dedo do usuário na tela.
Apesar de serem duas etapas sequenciais elas acontecem de maneira tão rápida que a impressão que o usuário tem é que ele está arrastando o retângulo na tela:
Para finalizar a nossa tela, ao término do movimento de arrasto, vou posicionar o retângulo em duas opções: retornar ao ponto inicial, exibindo apenas a ponta, ou ficar completamente visível na parte inferior da tela.
Como é uma decisão a ser tomada no fim da execução do gesto de arrasto do dedo, vou implementar esse trecho dentro do método onEnded. Se o deslocamentoVertical for menor que 30 unidades significa que o usuário arrastou o retângulo até um ponto que ele ficou totalmente visível. Neste caso, vou atribuir o valor zero a variável deslocamentoVertical fazendo com que o retângulo fique totalmente exposto na tela.
Caso contrário, significa que o usuário não arrastou o retângulo o suficiente e ele deve voltar a posição inicial onde ele fica quase completamente escondido. Isto é atribuir o valor descolamentoVertical 200 unidades.
O código final ficará da seguinte maneira:
import SwiftUI
struct ContentView: View {
// desloca 200 unidades para baixo do ponto inicial
@State var deslocamentoVertical : CGFloat = 200
var body: some View {
Spacer()
RoundedRectangle(cornerRadius: 10)
.foregroundStyle(.blue)
.frame(width: 300, height: 200)
.offset(y: descolamentoVertical)
.gesture(
DragGesture()
.onChanged { value in
withAnimation{
deslocamentoVertical = value.location.y
}
}
.onEnded { value in
withAnimation{
if(descolamentoVertical < 30){
descolamentoVertical = 0
}else{
descolamentoVertical = 200
}
}
}
)
}
}
O resultado final será:
Conclusão e outras formas de uso do DragGesture
Através do exemplo codificado foi possível conhecer a mecânica do uso dos gestos de arrasto no SwiftUI. Agora você pode fazer a sua implementação para o seu caso de uso.
Lembre-se que o parâmetro recebido nas funções onChanged e onEnded contém a tanto a posição do eixo Y como do eixo X, permitindo que você realize movimentações para qualquer ponto e direção da tela.
Além disso, você pode ajustar os parâmetros da animação para deixar o movimento mais rápido, mais elástico ou mais lento conforme for a sua necessidade e contexto. Veja o artigo Animações no SwiftUI sobre animações para entender melhore esses parâmetros.
Por fim, é possível modificar qualquer atributo de outros elementos na tela, em vez de apenas mover o objeto. Por exemplo, você pode aumentar o tamanho do retângulo ou alterar sua cor enquanto o usuário arrasta o dedo na tela.
Para ir além e aprender mais
Outros artigos interessantes também podem te ajudar na sua jornada de aprendizado:
Documentação oficial sobre gestos do Swift:
Dicas e tutoriais de como implementar Gestures: