iPhone: Kaydırıcı sürüklemesinin sonu nasıl tespit edilir?


96

Kullanıcı bir kaydırıcı işaretçisinin sürüklemesini bitirdiğinde olay nasıl tespit edilir?


1
Kullanın: [slider addTarget: self action: @selector (sliderStoppedDragging :) forControlEvents: UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
Henry Sou

Yanıtlar:


180

Sürükleme arasında herhangi bir veriye ihtiyacınız yoksa, basitçe ayarlamanız gerekenden:

[mySlider setContinuous: NO];

Bu şekilde, valueChangedyalnızca kullanıcı kaydırıcıyı hareket ettirmeyi bıraktığında olay alırsınız .

Swift 5 versiyonu:

mySlider.isContinuous = false

2
Bu sorunun en iyi cevabı budur. Keşke bunun cevabını değiştirebilseydik.
M. Porooshani

1
i.imgur.com/0Edd2xe.png?1 XCode sürüm 6.x, IDE'nin kendisi aracılığıyla setContinuous'ı ayarlama özelliğine sahiptir.
Abhijeet

1
Evet, en iyi cevap bu.
sabiland

3
Mükemmel cevap. İşte Swift 4 Kodu:self.mySlider.isContinuous = false
Marco Weber

2
Yazarın sorduğu bu değil. Sürekli kaymak istiyor ve ayrıca ne zaman duracağını bilmek istiyor.
lbsweek

120

UIControlEventValueChanged için gönderen ve olay olmak üzere iki parametre alan bir eylem ekleyebilirsiniz :

[slider addTarget:self action:@selector(onSliderValChanged:forEvent:) forControlEvents:UIControlEventValueChanged]

Ardından, işleyicinizdeki dokunma nesnesinin aşamasını kontrol edin:

- (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 ve 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
        }
    }
}

Bir eylem eklerken Arayüz Oluşturucu'da ayrıca eyleme hem gönderen hem de olay parametreleri ekleme seçeneğiniz olduğunu unutmayın.


1
Mükemmel çalışıyor! Bunun kaynağını nereden buldunuz?
Roi Mulia

2
teşekkürler @RoiMulia, onu ilk nerede gördüğümü hatırlamıyorum, kaydırıcılarda yıllardır kullanıyorum. Bazen kullanıcı parmağını kaldırdığında değer atlama eğiliminde olduğundan, UITouchPhaseEnded üzerindeki değişikliği yok saymak için kullanıyorum.
Devin Sürahi

2
Ayarlamayı unutmayın isContinuous = trueGözlerinde farklı UISlider.
krlbsk

2
Bu harika bir çözüm, ancak dokunma iptali ile ilgili bir sorunu var. TouchEvent numarasında "iptal edilen" bir olay olmasına rağmen, dokunma iptal edildiğinde tetiklenmez. Bu nedenle, Slider'dan touchCancel olayı için bir dinleyici eklemenizi de öneririm. Bu, tüm olasılıkları kapsamalıdır.
bnussey

2
Bazen fazın gidebildiğini gördüm: başladı, durağan, hareket etti ama sonra asla bitmedi veya iptal edilmedi. Her etkileşimin sona ermesini veya iptal edilmesini beklediğimden, bu benim kullanım durumum için sorunlu. Düzeltme yukarıda belirtilmiştir: ayrı bir dokunma iptal hedefi / eylemi kullanın.
Ürdün H

71

"İçeriye Rötuş Yap" ve "Dışında Rötuş Yap" bildirimlerini kullanıyorum.

Arayüz Oluşturucu:

Arabirim Oluşturucu'daki her iki bildirimi de alma yönteminize bağlayın. Yöntem şöyle görünebilir:

- (IBAction)lengthSliderDidEndSliding:(id)sender {
    NSLog(@"Slider did end sliding... Do your stuff here");
}

Kodda:

Programatik olarak bağlamak isterseniz, görünümünüzde buna benzer bir şeye sahip olursunuz (veya size uyan her yerde) arayın:

[_mySlider addTarget:self
              action:@selector(sliderDidEndSliding:) 
    forControlEvents:(UIControlEventTouchUpInside | UIControlEventTouchUpOutside)];

Alma yöntemi şöyle görünecektir:

- (void)sliderDidEndSliding:(NSNotification *)notification {
     NSLog(@"Slider did end sliding... Do your stuff here");
}

19

' UISliderNin bir alt sınıfı olduğundan UIControl, onun için bir hedef ve eylem belirleyebilirsiniz UIControlEventTouchUpInside.

Bunu kodla yapmak istiyorsanız, şuna benzer:

[self.slider addTarget:self action:@selector(dragEndedForSlider:)
    forControlEvents:UIControlEventTouchUpInside];

dragEndedForSlider:Dokunma bittiğinde bu size bir mesaj gönderecektir .

Ucunuzda yapmak istiyorsanız, bağlantı menüsünü almak için kaydırıcınızı kontrol tuşuna basarak tıklayabilir ve ardından "İçine Rötuş Yap" soketinden hedef nesneye sürükleyebilirsiniz.

Ayrıca için UIControlEventTouchUpOutsideve için bir hedef ve eylem eklemelisiniz UIControlEventTouchCancel.


1
@rob mayoff Üzgünüz ama UIControlEventTouchUpOutside'ı kullanmanız gerekiyor. Aksi takdirde, sürüklemeyi bitirdiğinizde parmağınız kaydırıcı üzerinde değilse seçici çağrılmaz.
user3164248

2
UISliderBu cevabı yazdığımdan beri davranışları değişti.
soygun mayoff

Bunu teyit edebilir mi ayrıca iOS 9'da UIControlEventTouchUpOutside için bir işleyici kayıt olmanız gerekir
LMS

UIControlEventTouchCancelİOS 9'da hiçbir zaman işleyiciyi çağıramadım . Ama sadece UIControlEventTouchUpInsideve UIControlEventTouchUpOutsidesadece çalıştırabiliyorum.
petrsyn

17

Swift 5 ve Swift 4

  1. touchUpInsideVe touchUpOutsideetkinlikler için hedef ekleyin . Bunu programlı olarak veya film şeridinden yapabilirsiniz. Programatik olarak bu şekilde yaparsınız

    slider.addTarget(self, action: #selector(sliderDidEndSliding), for: [.touchUpInside, .touchUpOutside])
    
  2. Kaydırıcı sürüklemesinin sonunu işlemek için işlevinizi yazın

    func sliderDidEndSliding() {
        print("end sliding")
    }
    

Merhaba. Sürüklemeye başladığımda videoyu nasıl duraklatabilirim?
kemdo

Bu, bir sürüklemenin gerekli olup olmadığını algılamaz ve sürüklemeden dokunarak tetiklenebilir.
Chewie Chorkie

9

Kullanabilirsiniz:

- (void)addTarget:(id)target action:(SEL)action 
                   forControlEvents:(UIControlEvents)controlEvents  

UISlider'da touchDown ve touchUp olaylarının ne zaman gerçekleştiğini algılamak için



5

Hızlı 3 cevap

Aynı problemi yaşadım ve sonunda bunu çalıştırdım, bu yüzden belki birine yardımcı olur. Your_Slider'ınızı film şeridindeki 'Değeri Değiştirildi'ye bağlayın ve kaydırıcı "Kaydırıcıya Dokunuldu" işlemine getirildiğinde ve "Kaydırıcı Bırakıldı" bırakıldığında.

@IBAction func your_Slider(_ sender: UISlider) {
    if (yourSlider.isTracking) {
        print("Slider Touched")
    } else {
        print("Slider Released")
    }
}

2
İyi bir çözüm, ancak dikkatli olun çünkü Sürüklemeye başladığınızda ve sürüklemeyi
bitirdiğinde

ve bazen piyasaya sürüldüğünde "Kaydırıcı Çıktı" olarak adlandırılmaz
Vadim


4

Swift 3.1

Bazen kaydırıcının sürükleme olaylarının sürekli olarak tetiklenmesini isteyebilirsiniz, ancak kaydırıcının hala sürüklenip sürüklenmediğine veya sürüklenmesini yeni bitirip bitirmediğine bağlı olarak farklı kod çalıştırma seçeneğiniz de vardır.

Bunu yapmak için, kaydırıcının isTrackingözelliğini kullanan Andy'nin yukarıdaki cevabını genişlettim . İki durumu kaydetmem gerekiyordu: sliderHasFinishedTrackingve sliderLastStoredValue.

Kodum doğru:

  • sürüklemeyi başlattıktan sonra bir eylem başlatmaz

  • kullanıcı yalnızca tek bir dokunuşla kaydırıcıyı dürttüğünde işlemi başlatır ( isTrackingkalan anlamına gelir 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
  }
}

4

Swift 4'te bu işlevi kullanabilirsiniz

1 İlk adım: - Kaydırıcıya hedef ekleme

self.distanceSlider.addTarget(self, action: #selector(self.sliderDidEndSliding(notification:)), for: ([.touchUpInside,.touchUpOutside]))

2 İkinci adım: - Bir işlev oluşturun

@objc func sliderDidEndSliding(notification: NSNotification)
{
   print("Hello-->\(distanceSlider.value)")
}

2

Belki de UIControlEventTouchUpInside 、 UIControlEventTouchUpOutside 、 UIControlEventTouchCancel olayları için hedef eklemelisiniz.

Aynı problemle daha önce karşılaştım çünkü UIControlEventTouchCancel olayı için hedef eklemiyorum .


1

Son zamanlarda benzer bir sorun yaşadım. İşte Swift'de yaptığım şey:

    theSlider.continuous = false;

Bu sürekli değeri tutan kod şunları okur:

public var continuous: Bool // if set, value change events are generated
    // any time the value changes due to dragging. default = YES

Varsayılan, EVET (doğru) gibi görünüyor. Bunu yanlış olarak ayarlamak istediğiniz şeyi yapar.


0

Böyle dene

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);
}

Bu, eylemi yalnızca sürükleme bittiğinde değil, kaydırıcının başparmağı her hareket ettiğinde gönderir.
rob mayoff

0

RxSwift:

self.slider.rx.controlEvent([.touchUpInside, .touchUpOutside])
    .bind(to: self.viewModel.endSlidingSlider)
    .disposed(by: self.disposeBag)

0

Kaydırıcı için bir eylem ve çıkış oluşturun (veya eylemden UISlider'a döküm göndereni yazabilirsiniz) ve Kullanıcı Arabiriminde Sürekli Güncellemeler onay kutusunun işaretini kaldırın. Bu şekilde, kaydırıcı değerini yalnızca kaydırıcı sürüklemeyi bıraktığında alacağız.

@IBAction func actionSlider(_ sender: Any) {
   let value = sliderSpeed.value.rounded()
}

görüntü açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.