Come rilevare l'evento quando l'utente ha terminato il trascinamento di un cursore a scorrimento?
Come rilevare l'evento quando l'utente ha terminato il trascinamento di un cursore a scorrimento?
Risposte:
Se non hai bisogno di dati durante il trascinamento, dovresti semplicemente impostare:
[mySlider setContinuous: NO];
In questo modo riceverai l' valueChangedevento solo quando l'utente smette di muovere il cursore.
Versione Swift 5 :
mySlider.isContinuous = false
Events [x] Continuous Updatesimpostazione per UISliderView. Deselezionando questa opzione si imposta continuousfalse / NO.
self.mySlider.isContinuous = false
Puoi aggiungere un'azione che accetta due parametri, mittente e un evento, per UIControlEventValueChanged:
[slider addTarget:self action:@selector(onSliderValChanged:forEvent:) forControlEvents:UIControlEventValueChanged]
Quindi controlla la fase dell'oggetto touch nel tuo gestore:
- (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
}
}
}
Nota in Interface Builder quando aggiungi un'azione, hai anche la possibilità di aggiungere all'azione i parametri del mittente e dell'evento.
isContinuous = truetuo file UISlider.
Uso le notifiche "Ritocco interno" e "Ritocco esterno".
Costruttore di interfacce:
Collega entrambe le notifiche in Interface Builder al tuo metodo di ricezione. Il metodo potrebbe essere simile a questo:
- (IBAction)lengthSliderDidEndSliding:(id)sender {
NSLog(@"Slider did end sliding... Do your stuff here");
}
In codice:
Se vuoi collegarlo in modo programmatico, avresti qualcosa di simile nella tua vista WillAppear (o ovunque ti si adatti) chiama:
[_mySlider addTarget:self
action:@selector(sliderDidEndSliding:)
forControlEvents:(UIControlEventTouchUpInside | UIControlEventTouchUpOutside)];
Il metodo di ricezione sarebbe simile a questo:
- (void)sliderDidEndSliding:(NSNotification *)notification {
NSLog(@"Slider did end sliding... Do your stuff here");
}
Poiché UISliderè una sottoclasse di UIControl, puoi impostare un obiettivo e un'azione per il suo UIControlEventTouchUpInside.
Se vuoi farlo in codice, assomiglia a questo:
[self.slider addTarget:self action:@selector(dragEndedForSlider:)
forControlEvents:UIControlEventTouchUpInside];
Questo ti invierà un dragEndedForSlider:messaggio quando il tocco finisce.
Se vuoi farlo con il pennino, puoi fare control-clic sul cursore per visualizzare il menu delle connessioni, quindi trascinare dalla presa "Ritocco interno" all'oggetto di destinazione.
Dovresti anche aggiungere un obiettivo e un'azione per UIControlEventTouchUpOutsidee per UIControlEventTouchCancel.
UISliderè cambiato da quando ho scritto questa risposta.
UIControlEventTouchCancelgestore in iOS 9. Ma sono in grado di invocare UIControlEventTouchUpInsidee UIControlEventTouchUpOutsidesolo.
Aggiungi target per touchUpInsideed touchUpOutsideeventi. Puoi farlo in modo programmatico o dallo storyboard. Ecco come lo fai in modo programmatico
slider.addTarget(self, action: #selector(sliderDidEndSliding), for: [.touchUpInside, .touchUpOutside])Scrivi la tua funzione per gestire la fine del trascinamento del cursore
func sliderDidEndSliding() {
print("end sliding")
}
Puoi usare:
- (void)addTarget:(id)target action:(SEL)action
forControlEvents:(UIControlEvents)controlEvents
per rilevare quando si verificano gli eventi touchDown e touchUp in UISlider
Penso che tu abbia bisogno dell'evento di controllo UIControlEventTouchUpInside.
Risposta rapida 3
Ho avuto lo stesso problema e alla fine è riuscito a far funzionare tutto, quindi forse aiuterà qualcuno. Collega il tuo_Slider a "Valore modificato" nello storyboard e quando lo slider si sposta "Slider Touched" azionato e quando lascialo "Slider rilasciato".
@IBAction func your_Slider(_ sender: UISlider) {
if (yourSlider.isTracking) {
print("Slider Touched")
} else {
print("Slider Released")
}
}
A volte potresti volere che gli eventi di trascinamento del cursore si attivino continuamente, ma hai la possibilità di eseguire un codice diverso a seconda che il cursore sia ancora trascinato o che sia appena stato trascinato.
Per fare ciò, ho ampliato la risposta di Andy sopra che utilizza la isTrackingproprietà del cursore . Avevo bisogno di registrare due stati: sliderHasFinishedTrackinge sliderLastStoredValue.
Il mio codice correttamente:
non attiva un'azione all'avvio del trascinamento
attiva l'azione se l'utente spinge il cursore con un solo tocco (il che significa che isTrackingrimane 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
}
}
In Swift 4 puoi usare questa funzione
1 Primo passo: - Aggiunta del bersaglio nel cursore
self.distanceSlider.addTarget(self, action: #selector(self.sliderDidEndSliding(notification:)), for: ([.touchUpInside,.touchUpOutside]))
2 Secondo passo: - Creare una funzione
@objc func sliderDidEndSliding(notification: NSNotification)
{
print("Hello-->\(distanceSlider.value)")
}
Ho avuto un problema simile di recente. Ecco cosa ho fatto in Swift:
theSlider.continuous = false;
Il codice che contiene questo valore continuo legge:
public var continuous: Bool // if set, value change events are generated
// any time the value changes due to dragging. default = YES
L'impostazione predefinita sembra essere YES (true). Impostarlo su false fa la cosa che desideri.
Prova in questo modo
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)
Crea un'azione e uno sbocco per il dispositivo di scorrimento (oppure puoi digitare il mittente del cast da azione a UISlider) e nell'interfaccia utente deseleziona la casella di controllo Aggiornamenti continui. In questo modo otterremo il valore dello slider solo quando lo slider smette di trascinare.
@IBAction func actionSlider(_ sender: Any) {
let value = sliderSpeed.value.rounded()
}