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 valueChangedevento apenas quando o usuário parar de mover o controle deslizante.
Versão Swift 5 :
mySlider.isContinuous = false
Events [x] Continuous Updatesconfiguração para UISliderView. Desmarcar isso define continuouscomo 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 = trueem 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 UIControlEventTouchUpOutsidee para UIControlEventTouchCancel.
UISlidermudou desde que escrevi esta resposta.
UIControlEventTouchCancelhandler no iOS 9. Mas sou capaz de invocar UIControlEventTouchUpInsidee UIControlEventTouchUpOutsideapenas.
Adicione alvo para eventos touchUpInsidee 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 isTrackingpropriedade do controle deslizante . Eu precisava registrar dois estados: sliderHasFinishedTrackinge 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 isTrackingpermanece 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()
}