Como detectar o evento quando o usuário encerrou o arrasto de um ponteiro deslizante?
Como detectar o evento quando o usuário encerrou o arrasto de um ponteiro deslizante?
Respostas:
Se você não precisa de nenhum dado entre o arrasto, você deve simplesmente definir:
[mySlider setContinuous: NO];
Dessa forma, você receberá o valueChanged
evento apenas quando o usuário parar de mover o controle deslizante.
Versão Swift 5 :
mySlider.isContinuous = false
Events [x] Continuous Updates
configuração para UISliderView. Desmarcar isso define continuous
como falso / NÃO.
self.mySlider.isContinuous = false
Você pode adicionar uma ação que leva dois parâmetros, remetente e um evento, para UIControlEventValueChanged:
[slider addTarget:self action:@selector(onSliderValChanged:forEvent:) forControlEvents:UIControlEventValueChanged]
Em seguida, verifique a fase do objeto de toque em seu manipulador:
- (void)onSliderValChanged:(UISlider*)slider forEvent:(UIEvent*)event {
UITouch *touchEvent = [[event allTouches] anyObject];
switch (touchEvent.phase) {
case UITouchPhaseBegan:
// handle drag began
break;
case UITouchPhaseMoved:
// handle drag moved
break;
case UITouchPhaseEnded:
// handle drag ended
break;
default:
break;
}
}
Swift 4 e 5
slider.addTarget(self, action: #selector(onSliderValChanged(slider:event:)), for: .valueChanged)
@objc func onSliderValChanged(slider: UISlider, event: UIEvent) {
if let touchEvent = event.allTouches?.first {
switch touchEvent.phase {
case .began:
// handle drag began
case .moved:
// handle drag moved
case .ended:
// handle drag ended
default:
break
}
}
}
Observe que no Interface Builder, ao adicionar uma ação, você também tem a opção de adicionar os parâmetros do remetente e do evento à ação.
isContinuous = true
em seu UISlider
.
Eu uso as notificações "Retoque interno" e "Retoque externo".
Interface Builder:
Conecte ambas as notificações no Interface Builder ao seu método de recebimento. O método pode ser assim:
- (IBAction)lengthSliderDidEndSliding:(id)sender {
NSLog(@"Slider did end sliding... Do your stuff here");
}
Em código:
Se você quiser conectá-lo programaticamente, terá algo assim em seu viewWillAppear (ou onde quer que seja adequado), chame:
[_mySlider addTarget:self
action:@selector(sliderDidEndSliding:)
forControlEvents:(UIControlEventTouchUpInside | UIControlEventTouchUpOutside)];
O método de recebimento seria semelhante a este:
- (void)sliderDidEndSliding:(NSNotification *)notification {
NSLog(@"Slider did end sliding... Do your stuff here");
}
Como UISlider
é uma subclasse de UIControl
, você pode definir um alvo e uma ação para ele UIControlEventTouchUpInside
.
Se você quiser fazer isso em código, terá a seguinte aparência:
[self.slider addTarget:self action:@selector(dragEndedForSlider:)
forControlEvents:UIControlEventTouchUpInside];
Isso enviará uma dragEndedForSlider:
mensagem a você quando o toque terminar.
Se quiser fazer isso na ponta, você pode clicar com o botão direito do mouse no controle deslizante para obter o menu de conexões e, em seguida, arrastar do soquete “Retocar dentro” para o objeto de destino.
Você também deve adicionar um alvo e uma ação para UIControlEventTouchUpOutside
e para UIControlEventTouchCancel
.
UISlider
mudou desde que escrevi esta resposta.
UIControlEventTouchCancel
handler no iOS 9. Mas sou capaz de invocar UIControlEventTouchUpInside
e UIControlEventTouchUpOutside
apenas.
Adicione alvo para eventos touchUpInside
e touchUpOutside
. Você pode fazer isso programaticamente ou a partir do storyboard. É assim que você faz isso programaticamente
slider.addTarget(self, action: #selector(sliderDidEndSliding), for: [.touchUpInside, .touchUpOutside])
Escreva sua função para lidar com o final do arrasto do controle deslizante
func sliderDidEndSliding() {
print("end sliding")
}
Você pode usar:
- (void)addTarget:(id)target action:(SEL)action
forControlEvents:(UIControlEvents)controlEvents
para detectar quando os eventos touchDown e touchUp ocorrem no UISlider
Acho que você precisa do evento de controle UIControlEventTouchUpInside
.
Resposta rápida 3
Eu tive o mesmo problema e eventualmente fiz isso funcionar, então talvez ajude alguém. Conecte your_Slider a 'Value Changed' no storyboard e quando o slider for movido, "Slider Touched" acionado e quando for solto "Slider Released".
@IBAction func your_Slider(_ sender: UISlider) {
if (yourSlider.isTracking) {
print("Slider Touched")
} else {
print("Slider Released")
}
}
Às vezes, você desejará que os eventos de arrastar do controle deslizante sejam disparados continuamente, mas tem a opção de executar códigos diferentes, dependendo se o controle deslizante ainda está sendo arrastado ou acabou de ser arrastado.
Para fazer isso, expandi a resposta de Andy acima que faz uso da isTracking
propriedade do controle deslizante . Eu precisava registrar dois estados: sliderHasFinishedTracking
e sliderLastStoredValue
.
Meu código corretamente:
não dispara uma ação ao iniciar o arrasto
dispara a ação se o usuário apenas empurrar o controle deslizante com um único toque (o que significa que isTracking
permanece false
)
class SliderExample: UIViewController {
var slider: UISlider = UISlider()
var sliderHasFinishedTracking: Bool = true
var sliderLastStoredValue: Float!
override func loadView() {
super.loadView()
slider.minimumValue = 100.0
slider.maximumValue = 200.0
slider.isContinuous = true
slider.value = 100.0
self.sliderLastStoredValue = slider.value
slider.addTarget(self, action: #selector(respondToSlideEvents), for: .valueChanged)
// add your slider to the view however you like
}
func respondToSlideEvents(sender: UISlider) {
let currentValue: Float = Float(sender.value)
print("Event fired. Current value for slider: \(currentValue)%.")
if(slider.isTracking) {
self.sliderHasFinishedTracking = false
print("Action while the slider is being dragged ⏳")
} else {
if(self.sliderHasFinishedTracking && currentValue == self.sliderLastStoredValue){
print("Slider has finished tracking and its value hasn't changed, " +
"yet event was fired anyway. 🤷") // No need to take action.
} else {
self.sliderHasFinishedTracking = true
print("Action upon slider drag/tap finishing ⌛️")
}
}
self.sliderLastStoredValue = currentValue
}
}
No Swift 4 você pode usar esta função
1 Primeira etapa: - Adicionando o alvo no controle deslizante
self.distanceSlider.addTarget(self, action: #selector(self.sliderDidEndSliding(notification:)), for: ([.touchUpInside,.touchUpOutside]))
2 Segunda etapa: - Criar uma função
@objc func sliderDidEndSliding(notification: NSNotification)
{
print("Hello-->\(distanceSlider.value)")
}
Tive um problema semelhante recentemente. Aqui está o que eu fiz no Swift:
theSlider.continuous = false;
O código que contém esse valor contínuo é:
public var continuous: Bool // if set, value change events are generated
// any time the value changes due to dragging. default = YES
O padrão parece ser SIM (verdadeiro). Definir como false faz o que você deseja.
Tente assim
customSlider.minimumValue = 0.0;
customSlider.maximumValue = 10.0;
[customSlider addTarget:self action:@selector(changeSlider:) forControlEvents:UIControlEventValueChanged];
-(void)changeSlider:(id)sender{
UISlider *slider=(UISlider *)sender;
float sliderValue=(float)(slider.value );
NSLog(@"sliderValue = %f",sliderValue);
}
RxSwift:
self.slider.rx.controlEvent([.touchUpInside, .touchUpOutside])
.bind(to: self.viewModel.endSlidingSlider)
.disposed(by: self.disposeBag)
Crie uma ação e saída para o controle deslizante (ou você pode transformar o remetente da ação para o UISlider) e, na IU, desmarque a caixa de seleção Atualizações Contínuas. Dessa forma, obteremos o valor do controle deslizante apenas quando o controle deslizante parar de arrastar.
@IBAction func actionSlider(_ sender: Any) {
let value = sliderSpeed.value.rounded()
}