iPhone: Làm thế nào để phát hiện điểm cuối của thao tác kéo thanh trượt?


94

Làm thế nào để phát hiện sự kiện khi người dùng đã kết thúc việc kéo con trỏ thanh trượt?


1
Sử dụng: [slider addTarget: self action: @selector (sliderStoppedDragging :) forControlEvents: UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
Henry Sou

Câu trả lời:


171

Nếu bạn không cần bất kỳ dữ liệu nào giữa quá trình kéo, bạn chỉ cần đặt:

[mySlider setContinuous: NO];

Bằng cách này, bạn sẽ chỉ nhận được valueChangedsự kiện khi người dùng ngừng di chuyển thanh trượt.

Phiên bản Swift 5 :

mySlider.isContinuous = false

2
Đây là câu trả lời tốt nhất cho câu hỏi này. Tôi ước chúng ta có thể thay đổi câu trả lời cho điều này.
M. Porooshani

1
i.imgur.com/0Edd2xe.png?1 Phiên bản XCode 6.x có tính năng thiết lập setContinuous thông qua chính IDE.
Abhijeet

1
Vâng, câu trả lời tốt nhất là điều này.
sabiland

1
Xcode 7.3 Interface Builder có Events [x] Continuous Updatescài đặt cho UISliderView. Bỏ chọn này sẽ đặt continuousthành false / NO.
leanne

3
Câu trả lời chính xác. Đây là mã Swift 4:self.mySlider.isContinuous = false
Marco Weber

115

Bạn có thể thêm một hành động có hai tham số, người gửi và một sự kiện, cho UIControlEventValueChanged:

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

Sau đó, kiểm tra giai đoạn của đối tượng cảm ứng trong trình xử lý của bạn:

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

Lưu ý trong Trình tạo giao diện khi thêm một hành động, bạn cũng có tùy chọn để thêm cả thông số người gửi và sự kiện vào hành động.


1
Hoạt động hoàn hảo! Bạn lấy nguồn từ đâu cho điều đó?
Roi Mulia

2
cảm ơn @RoiMulia, tôi không nhớ nơi tôi nhìn thấy nó lần đầu tiên, tôi đã sử dụng trong thanh trượt trong nhiều năm. Đôi khi tôi sử dụng nó để bỏ qua thay đổi trên UITouchPhaseEnded vì giá trị có xu hướng nhảy khi người dùng nhấc ngón tay lên.
Devin Pitcher

2
Hãy nhớ đặt isContinuous = truetrong của bạn UISlider.
krlbsk

2
Đây là một giải pháp tuyệt vời, tuy nhiên nó có vấn đề với việc hủy chạm. Mặc dù có sự kiện "bị hủy" trong enum touchEvent, nó không được kích hoạt khi thao tác chạm bị hủy. Do đó, tôi cũng khuyên bạn nên thêm trình lắng nghe cho sự kiện touchCancel từ Slider. Điều này sẽ bao gồm tất cả các khả năng.
bnussey 19/07/18

2
Tôi thấy rằng đôi khi giai đoạn có thể diễn ra: bắt đầu, đứng yên, di chuyển, nhưng sau đó không bao giờ kết thúc hoặc bị hủy bỏ. Đây là vấn đề đối với trường hợp sử dụng của tôi vì tôi mong đợi mọi tương tác sẽ kết thúc hoặc bị hủy. Cách khắc phục được lưu ý ở trên: sử dụng mục tiêu / hành động hủy chạm riêng biệt.
Jordan H

71

Tôi sử dụng thông báo "Chạm lên bên trong" và "Chạm lên bên ngoài".

Trình tạo giao diện:

Kết nối cả hai thông báo trong Trình tạo giao diện với phương thức nhận của bạn. Phương thức có thể trông như thế này:

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

Trong mã:

Nếu bạn muốn kết nối nó theo chương trình, bạn sẽ có một cái gì đó như thế này trong viewWillAppear (hoặc bất cứ nơi nào nó phù hợp với bạn) hãy gọi:

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

Phương thức nhận sẽ giống như sau:

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

19

UISliderlà một lớp con của UIControl, bạn có thể đặt mục tiêu và hành động cho nó UIControlEventTouchUpInside.

Nếu bạn muốn làm điều đó trong mã, nó sẽ giống như sau:

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

Điều đó sẽ gửi cho bạn một dragEndedForSlider:tin nhắn khi chạm kết thúc.

Nếu bạn muốn làm điều đó trong nib của mình, bạn có thể điều khiển khi nhấp vào thanh trượt để nhận menu kết nối của nó, sau đó kéo từ ổ cắm “Touch Up Inside” vào đối tượng mục tiêu.

Bạn cũng nên thêm mục tiêu và hành động cho UIControlEventTouchUpOutsidevà cho UIControlEventTouchCancel.


1
@rob mayoff Xin lỗi nhưng bạn cần sử dụng UIControlEventTouchUpOutside. Nếu không, bộ chọn sẽ không được gọi nếu ngón tay của bạn không ở trên thanh trượt khi bạn kéo xong.
user3164248

2
Hành vi của UISliderđã thay đổi kể từ khi tôi viết câu trả lời này.
cướp mayoff

Có thể xác nhận rằng bạn cũng cần đăng ký một trình xử lý cho UIControlEventTouchUpOutside trong iOS 9.
lms

Tôi đã không bao giờ có thể gọi UIControlEventTouchCancelhandler trong iOS 9. Nhưng tôi có thể gọi UIControlEventTouchUpInsideUIControlEventTouchUpOutsidechỉ.
petrsyn

17

Swift 5 và Swift 4

  1. Thêm mục tiêu cho touchUpInsidetouchUpOutsidecác sự kiện. Bạn có thể làm điều đó theo chương trình hoặc từ bảng phân cảnh. Đây là cách bạn thực hiện theo chương trình

    slider.addTarget(self, action: #selector(sliderDidEndSliding), for: [.touchUpInside, .touchUpOutside])
  2. Viết hàm của bạn để xử lý phần cuối của quá trình kéo thanh trượt

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

xin chào. Làm cách nào để tạm dừng video khi bắt đầu kéo?
kemdo 12/07/18

Điều này không phát hiện ra liệu một lần kéo đã từng xảy ra hay chưa và có thể được kích hoạt bằng cách chỉ cần chạm nhẹ mà không cần kéo.
Chewie The Chorkie

9

Bạn có thể dùng:

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

để phát hiện khi nào sự kiện touchDown và touchUp xảy ra trong UISlider



5

Câu trả lời Swift 3

Tôi đã gặp vấn đề tương tự và cuối cùng đã giải quyết được vấn đề này, vì vậy có thể nó sẽ giúp ích cho ai đó. Kết nối your_Slider với 'Giá trị đã thay đổi' trong bảng phân cảnh và khi thanh trượt di chuyển "Đã chạm vào thanh trượt" được kích hoạt và khi nào buông ra "Đã phát hành thanh trượt".

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

2
Giải pháp tốt, nhưng hãy cẩn thận vì Slider Released được gọi khi bắt đầu kéo kết thúc quá trình kéo
Guy Daher

và đôi khi không được gọi là "Slider Released" khi phát hành
Vadim,


4

Swift 3.1

Đôi khi bạn sẽ muốn các sự kiện kéo của thanh trượt kích hoạt liên tục, nhưng có tùy chọn thực thi mã khác nhau tùy thuộc vào việc thanh trượt vẫn đang được kéo hay vừa được kéo xong.

Để làm điều này, tôi đã mở rộng câu trả lời của Andy ở trên sử dụng thuộc tính của thanh trượt isTracking. Tôi cần ghi lại hai trạng thái: sliderHasFinishedTrackingsliderLastStoredValue .

Mã của tôi đúng:

  • không kích hoạt một hành động khi bắt đầu kéo

  • kích hoạt hành động nếu người dùng chỉ di chuyển thanh trượt bằng một lần nhấn (nghĩa là isTrackingvẫn còn 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

Trong Swift 4, bạn có thể sử dụng chức năng này

1 Bước ngón tay: - Thêm mục tiêu trong thanh trượt

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

2 Bước thứ hai: - Tạo một hàm

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

2

Có lẽ bạn nên thêm mục tiêu cho các sự kiện UIControlEventTouchUpInside 、 UIControlEventTouchUpOutside 、 UIControlEventTouchCancel.

Tôi đã gặp vấn đề tương tự trước đây, vì tôi không thêm đích cho sự kiện UIControlEventTouchCancel .


1

Tôi đã gặp vấn đề tương tự gần đây. Đây là những gì tôi đã làm trong Swift:

    theSlider.continuous = false;

Mã giữ giá trị liên tục này đọc:

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

Giá trị mặc định dường như là CÓ (true). Đặt nó thành false sẽ làm được điều bạn muốn.


0

Hãy thử như thế này

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

Điều đó sẽ gửi hành động mỗi khi ngón tay cái của thanh trượt di chuyển, không chỉ khi quá trình kéo kết thúc.
cướp mayoff

0

RxSwift:

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

0

Tạo một hành động và lối thoát cho thanh trượt (hoặc bạn có thể nhập người gửi từ hành động đến UISlider) và trong giao diện người dùng Bỏ chọn hộp kiểm Cập nhật liên tục. Bằng cách này, chúng ta sẽ chỉ nhận được giá trị thanh trượt khi thanh trượt ngừng kéo.

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

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.