Estou tentando implementar uma interface de usuário de corte de vídeo no SwiftUI da seguinte maneira:
struct SimpleTrimmer: View {
@State private var startPosition: CGFloat = 0
@GestureState private var isDragging: Bool = false
@State private var lastStartPosition: CGFloat = .zero
@State private var frameWidth:CGFloat = 300
var body: some View {
HStack(spacing: 10) {
Image(systemName: "chevron.compact.left")
.frame(height:70)
.frame(width:20)
.padding(.horizontal, 5)
.background(Color.blue)
.offset(x: startPosition)
.gesture(
DragGesture(minimumDistance: 0)
.updating($isDragging, body: { value, out, transaction in
out = true
})
.onChanged { value in
let translation = value.translation.width
startPosition = translation + lastStartPosition
}.onEnded { _ in
lastStartPosition = startPosition
NSLog("Last start position \(lastStartPosition)")
}
)
Spacer()
Image(systemName: "chevron.compact.right")
.frame(height:70)
.frame(width:20)
.padding(.horizontal, 5)
.background(Color.blue)
}
.foregroundColor(.black)
.font(.title3.weight(.semibold))
.padding(.horizontal, 7)
.padding(.vertical, 3)
.background(.yellow)
.clipShape(RoundedRectangle(cornerRadius: 7))
.frame(width: frameWidth)
// .offset(x: startPosition)
.onGeometryChange(for: CGFloat.self) { proxy in
proxy.size.width
} action: { width in
print("width = \(width)")
}
}
}
Isso funciona para mover a mão esquerda do trimmer quando arrastado. O que eu preciso também é encolher a SimpleTrimmer
visualização conforme as extremidades são arrastadas. Simplesmente não funciona, não importa o que eu faça (como ajustar o deslocamento e a largura do HStack principal, etc.).
Para que o quadro de fundo mude em coordenação com o gesto de arrastar, você precisa ajustar a largura do fundo conforme o arrasto acontece. No momento, a largura é fixa, então nenhuma mudança é vista.
Eu sugeriria as seguintes mudanças:
Use a
GestureState
variável para registrar o deslocamento do arrasto. Isso é automaticamente redefinido para 0 quando o gesto de arrastar termina, o que é conveniente.Use o deslocamento de arrasto para controlar o preenchimento inicial, em vez de aplicar um deslocamento x.
O mesmo preenchimento inicial deve ser aplicado ao aparador (chevron) e também ao fundo preenchido.
O fundo preenchido pode ser desenhado como um
RoundedRectangle
, em vez de usar uma forma de clipe. Isso facilita a aplicação do padding.Aqui está uma versão atualizada:
EDITAR Seguindo seu comentário, tentei adicionar um gesto de arrastar ao aparador (chevron) à direita, esperando que o preenchimento final pudesse ser ajustado da mesma forma que o preenchimento inicial acima.
Quando tentei, o movimento do aparador era instável. Acho que a razão para isso é porque há uma interdependência entre o tamanho do espaçador e o acolchoamento nos aparadores. Embora parecesse funcionar para o caso do acolchoamento principal, não funciona bem com o acolchoamento posterior.
Funciona melhor se você definir um x-offset nos trimmers, como você estava usando originalmente. Isso significa encontrar nomes melhores para as variáveis de estado também!
Aqui está uma versão atualizada com gestos de arrastar em ambos os aparadores: