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' valueChanged
evento solo quando l'utente smette di muovere il cursore.
Versione Swift 5 :
mySlider.isContinuous = false
Events [x] Continuous Updates
impostazione per UISliderView. Deselezionando questa opzione si imposta continuous
false / 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 = true
tuo 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 UIControlEventTouchUpOutside
e per UIControlEventTouchCancel
.
UISlider
è cambiato da quando ho scritto questa risposta.
UIControlEventTouchCancel
gestore in iOS 9. Ma sono in grado di invocare UIControlEventTouchUpInside
e UIControlEventTouchUpOutside
solo.
Aggiungi target per touchUpInside
ed touchUpOutside
eventi. 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 isTracking
proprietà del cursore . Avevo bisogno di registrare due stati: sliderHasFinishedTracking
e 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 isTracking
rimane 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()
}