How to enable “tap and slide” in a UISlider?

后端 未结 14 554
不知归路
不知归路 2020-12-03 20:54

What I want to get is a UISlider which lets the user not only slide when he starts on its thumbRect, but also when he taps elsewhere. When the user

14条回答
  •  一生所求
    2020-12-03 21:48

    I completed @DWilliames solution for a UISlider subclass containing minimum and maximumValueImages.

    Additionally I implemented a functionality for user touches in the areas outside the trackArea (means either the area around the minimum or the maximumValueImage). Touching these areas moves the slider/changes the value in intervals.

    - (void) tapAndSlide: (UILongPressGestureRecognizer*) gesture {
        CGPoint touchPoint = [gesture locationInView: self];
        CGRect trackRect = [self trackRectForBounds: self.bounds];
        CGFloat thumbWidth = [self thumbRectForBounds: self.bounds trackRect: trackRect value: self.value].size.width;
        CGRect trackArea = CGRectMake(trackRect.origin.x, 0, trackRect.size.width, self.bounds.size.height);
        CGFloat value;
    
    if (CGRectContainsPoint(trackArea, touchPoint)) {
        if (touchPoint.x <= trackArea.origin.x + thumbWidth/2.0) {
            value = self.minimumValue;
        }
        else if (touchPoint.x >= trackArea.origin.x + trackArea.size.width - thumbWidth/2.0) {
            value = self.maximumValue;
        }
        else {
            CGFloat percentage = (touchPoint.x - trackArea.origin.x - thumbWidth/2.0)/(trackArea.size.width - thumbWidth);
            CGFloat delta = percentage*(self.maximumValue - self.minimumValue);
            value = self.minimumValue + delta;
        }
    
        if (value != self.value) {
            if (gesture.state == UIGestureRecognizerStateBegan) {
                [UIView animateWithDuration: 0.2 delay: 0 options: UIViewAnimationOptionCurveEaseInOut animations: ^{
                    [self setValue: value animated: YES];
    
                } completion: ^(BOOL finished) {
                    [self sendActionsForControlEvents: UIControlEventValueChanged];
                }];
            }
            else {
                [self setValue: value animated: YES];
                [self sendActionsForControlEvents: UIControlEventValueChanged];
            }
        }
    }
    else {
        if (gesture.state == UIGestureRecognizerStateBegan) {
            if (touchPoint.x <= trackArea.origin.x) {
                if (self.value == self.minimumValue) return;
                value = self.value - 1.5;
            }
            else {
                if (self.value == self.maximumValue) return;
                value = self.value + 1.5;
            }
            CGFloat duration = 0.1;
            [UIView animateWithDuration: duration delay: 0 options: UIViewAnimationOptionCurveEaseInOut animations: ^{
                [self setValue: value animated: YES];
            } completion: ^(BOOL finished) {
                [self sendActionsForControlEvents: UIControlEventValueChanged];
            }];
        }
    }
    }
    

提交回复
热议问题