0

I'm trying to extend the current Picker component for ios in react native:

I would like to add the possibility to listen for startDragging and endDragging, startDecelerating and endDecelerating events.

I've found there that we can actually know if the user is currently dragging the Picker by checking its subviews dragging and decelerating flags. That's good but an event/delegate like pattern would suit the React native bridging model better.

Could you please suggest me how to listen to the Picker subviews dragging and decelerating values changes?

--- EDIT ---

Here is what I've tried so far:

I edited the Picker Manager file and added this:

// ...

@implementation RCTPickerManager

RCT_EXPORT_MODULE()

- (UIView *)view
{
  //return [RCTPicker new];

  RCTPicker* picker = [RCTPicker new];

  [self setDelegateForScrollViews:picker];

  return picker;
}

// ...

RCT_EXPORT_VIEW_PROPERTY(onScrollChange, RCTBubblingEventBlock)

// ...

-(void)setDelegateForScrollViews:(UIView*)view
{
  if([view isKindOfClass:[UIScrollView class]]){
    UIScrollView* scroll_view = (UIScrollView*) view;
    RCTLogInfo(@"DEBUG setting a delegate on SV");
    scroll_view.delegate = self;
  }
  else {
    for(UIView *sub_view in [view subviews]){
      [self setDelegateForScrollViews:sub_view];
    }
  }
}

// UIScrollViewDelegate methods

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
  RCTLogInfo(@"DEBUG scrollViewWillBeginDragging");
  ((RCTPicker*)self.view).onScrollChange(@{ @"state": [NSNumber numberWithBool:YES] });
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
                  willDecelerate:(BOOL)decelerate {
  RCTLogInfo(@"DEBUG scrollViewDidEndDragging");
  ((RCTPicker*)self.view).onScrollChange(@{ @"state": [NSNumber numberWithBool:NO] });
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
  RCTLogInfo(@"DEBUG scrollViewDidEndDecelerating");
  // TODO
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
  RCTLogInfo(@"DEBUG scrollViewDidEndScrollingAnimation");
}

@end

But the UIScrollView Delegate methods are never raised when I scroll the picker :(...

Anyone any idea?

Żabojad
  • 2,946
  • 2
  • 32
  • 39

1 Answers1

0

Try subclassing the picker view and implementing the scrollview delegate methods. Don't forget to call super. I don't see why you're wanting to do this though. These functions are hidden by design. What are you trying to achieve by this? Even if you have a legit reason, you should probably reconsider what you are trying to do. If you really need to know when a user is scrolling to select something, use a UITableView and you can get its scrollview delegate events.

Hobbes the Tige
  • 3,753
  • 2
  • 22
  • 21
  • I need this because of the React native specific context. I need to prevent re-rendering the picker when the user is scrolling, because it causes bugs. Now about your suggestion, RCTPicker is already subclassing UIPickerView so I do not see how it will change anything? Also as per the link I've pasted (and I've tried it successfully), it is the subviews of the UIPickerView that are actually scrolling. How can we set delegates on those subviews from the UIPickerView? – Żabojad Feb 27 '19 at 08:03
  • The link I'm talking about: https://stackoverflow.com/questions/9202283/uipickerview-detect-rolling-wheel-start-and-stop – Żabojad Feb 27 '19 at 08:05
  • Did you try adding a pan gesture recognizer on the view? – Hobbes the Tige Feb 28 '19 at 18:07