问题
I just discovered that if I do the following:
- Click the button that animates a
UIPickerView
into my view - Quickly start the wheel rolling towards, then past, the last item
- Dismiss the view with a button
Then it has not yet selected the last item yet.
I tried this by simply outputting to the console whenever the didSelectRow
method was fired, and it fires when the wheel stabilizes on the last item.
Can I detect that the wheel is still rolling, so that I can delay checking it for a selected value until it stabilizes?
If it matters, I'm programming in MonoTouch, but I can read Objective-C code well enough to reimplement it, if you have a code example that is.
回答1:
I think you can just check if the UIPickerView is in the middle of animating and wait for it to stop. This was answered here link
回答2:
As animation keys don't work, I wrote this simple function that works for detecting if a UIPickerView is currently moving.
-(bool) anySubViewScrolling:(UIView*)view
{
if( [ view isKindOfClass:[ UIScrollView class ] ] )
{
UIScrollView* scroll_view = (UIScrollView*) view;
if( scroll_view.dragging || scroll_view.decelerating )
{
return true;
}
}
for( UIView *sub_view in [ view subviews ] )
{
if( [ self anySubViewScrolling:sub_view ] )
{
return true;
}
}
return false;
}
It ends up returning true five levels deep.
回答3:
Since animationKeys
seems to not work anymore, I have another solution. If you check the subviews of UIPickerView
, you'll see that there is a UIPickerTableView
for each component.
This UIPickerTableView
is indeed a subclass of UITableView
and of course of UIScrollView
. Therefore, you can check its contentOffset
value to detect a difference.
Besides, its scrollViewDelegate
is nil by default, so I assume you can safely set an object of yours to detect scrollViewWillBeginDragging
, scrollViewDidEndDecelerating
, etc.
By keeping a reference to each UIPickerTableView
, you should be able to implement an efficient isWheelRolling
method.
回答4:
Expanded @iluvatar_GR answer
extension UIView {
func isScrolling () -> Bool {
if let scrollView = self as? UIScrollView {
if (scrollView.isDragging || scrollView.isDecelerating) {
return true
}
}
for subview in self.subviews {
if ( subview.isScrolling() ) {
return true
}
}
return false
}
func waitTillDoneScrolling (completion: @escaping () -> Void) {
var isMoving = true
DispatchQueue.global(qos: .background).async {
while isMoving == true {
isMoving = self.isScrolling()
}
DispatchQueue.main.async {
completion()}
}
}
}
回答5:
Swift 4 (updated) version with extension of @DrainBoy answers
extension UIView {
func isScrolling () -> Bool {
if let scrollView = self as? UIScrollView {
if (scrollView.isDragging || scrollView.isDecelerating) {
return true
}
}
for subview in self.subviews {
if ( subview.isScrolling() ) {
return true
}
}
return false
}
}
回答6:
Expanded @iluvatar_GR, @Robert_at_Nextgensystems answer
Used Gesture, UIScrollView isDragging or isDecelerating.
// Call it every time when Guesture action.
@objc func respondToSwipeGesture(gesture: UIGestureRecognizer) {
// Changes the button name to scrolling at the start of scrolling.
DispatchQueue.main.async {
self._button.setTitle("Scrolling...", for: .normal)
self._button.isEnabled = false
self._button.backgroundColor = Utils.hexStringToUIColor(hex: "FF8FAE")
}
// Indication according to scrolling status
_datePicker.waitTillDoneScrolling(completion: {
print("completion")
DispatchQueue.main.async {
self._button.setTitle("Completion", for: .normal)
self._button.isEnabled = true
self._button.backgroundColor = Utils.hexStringToUIColor(hex: "7CB0FF")
}
})
}
[SWIFT4] Share Example Source link!
enter Sample Source link
- Reference : How to recognize swipe in all 4 directions
回答7:
You can use a SwipeGestureRecognizer on the picker. I assume this is not a perfect solution at all.
- (void)viewDidLoad
{
[super viewDidLoad];
_pickerSwipeGestureRecognizer.delegate = self;
[_pickerSwipeGestureRecognizer setDirection:(UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp)];
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
if([gestureRecognizer isEqual:_pickerSwipeGestureRecognizer]){
NSLog(@"start");
}
}
- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSLog(@"end");
}
来源:https://stackoverflow.com/questions/9202283/uipickerview-detect-rolling-wheel-start-and-stop