UISlider and UIScrollView

后端 未结 7 1829
猫巷女王i
猫巷女王i 2020-12-13 01:11

I have a UISlider as part of a view that is loaded into a UIScrollView with paging enabled. I\'ve noticed an unexpected behavior. If the user tries

7条回答
  •  星月不相逢
    2020-12-13 01:47

    My problem was a superset of this issue - I've got UISliders inside UITableViewCells and the whole UITableView is a page inside a UIScrollView. The sliders were wreaking havoc on the interactions with the other two and the subclassing solutions did not work. Here's what I came up with that's working great: send notifications when the sliders move and have the UITableView and UIScrollView disableScrolling on during this time. Note in the picture below: my sliders are horizontal, my tableview is vertical, and my UIScrollView has horizontal pages.

    UISlider in a UITableView in a UIScrollView

    The UITableViewCell picks up events for the programmatically-created slider:

    self.numberSlider = [[UISlider alloc] init];
    [self.numberSlider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
    [self.numberSlider addTarget:self action:@selector(sliderTouchDown:) forControlEvents:UIControlEventTouchDown];
    [self.numberSlider addTarget:self action:@selector(sliderTouchUp:) forControlEvents:UIControlEventTouchUpInside];
    [self.numberSlider addTarget:self action:@selector(sliderTouchUp:) forControlEvents:UIControlEventTouchUpOutside];
    

    For the purposes of this tutorial, we only care about touchDown and Up:

    - (void)sliderTouchDown:(UISlider *)sender
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFY_SLIDER_TOUCH_BEGAN object:nil];
    }
    
    - (void)sliderTouchUp:(UISlider *)sender
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFY_SLIDER_TOUCH_ENDED object:nil];
    }
    

    Now, we catch in these notifications in both the UITableView (note that the tableview is in a VC but I'm sure this would work if you subclassed):

    - (void)viewDidLoad
    {
        // other stuff
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sliderTouchDown:) name:NOTIFY_SLIDER_TOUCH_BEGAN object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sliderTouchUp:) name:NOTIFY_SLIDER_TOUCH_ENDED object:nil];
    }
    
    - (void)sliderTouchDown:(NSNotification *)notify
    {
        self.treatmentTableView.scrollEnabled = NO;
    }
    
    - (void)sliderTouchUp:(NSNotification *)notify
    {
        self.treatmentTableView.scrollEnabled = YES;
    }
    

    and the UIScrollView (same as above, enclosed in a VC):

    - (void)viewDidLoad
    {
        // other stuff
    
        // Register for slider notifications
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(disableScrolling:) name:NOTIFY_SLIDER_TOUCH_BEGAN object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enableScrolling:) name:NOTIFY_SLIDER_TOUCH_ENDED object:nil];
    }
    
    - (void)disableScrolling:(NSNotification *)notify
    {
        self.scrollView.scrollEnabled = NO;
    }
    
    - (void)enableScrolling:(NSNotification *)notify
    {
        self.scrollView.scrollEnabled = YES;
    }
    

    I'd love to hear a more elegant solution, but this one definitely gets the job done. When you use a slider, the table and scrollviews hold still and when you click outside the sliders, the tableview and scrollviews move as expected. Also - notice that I could use non-subclassed instances of all 3 components in this solution. Hope this helps someone!

提交回复
热议问题