如何在UISlider中启用"点按和滑动"?

Nor*_*ert 18 uislider uigesturerecognizer ios uitapgesturerecognizer

我想要的是一个UISlider让用户不仅可以在他开始时滑动thumbRect,而且还可以在其他地方点击的时候滑动.当用户点击滑块但在滑块之外时thumbRect,滑块应跳转到该值,然后仍然保持用户的滑动手势.

到目前为止我尝试过的是在这个建议中实现UIGestureRecognizer的子类.当它thumbRect发生在外面某处的触地时,它就开始了.问题是滑块设置其值但随后进一步滑动手势被忽略,因为触摸识别器已经窃取了触摸.

如何实现滑块,您可以在任何地方点按但仍然可以立即滑动?


编辑:ali59a非常友好地添加我现在所做的一个例子.这需要再次抬起手指,之后我可以触摸并拖动滑动(水龙头不是我想要的,我需要立即'触摸和滑动').

Dav*_*mes 23

我不确定你是否还在寻找答案,但我今天只是在看这个问题; 我设法让它为我工作.

它的关键是使用a UILongPressGestureRecognizer而不是a UITapGestureRecognizer,然后我们可以minimumPressDuration将识别器设置为0; 使它充当水龙头识别器,除了你现在可以实际检查它的状态.

把ali59a建议起来对你有用,只需UITapGestureRecognizer用a 代替UILongPressGestureRecognizer.但是,我发现这似乎并没有将thumbRect直接放在我的拇指下面.它看起来有点偏离我.

我为我的项目创建了自己的UISlider子类,这就是我为我实现"点击和滑动功能"的方法.

在我的init方法中:

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(tapAndSlide:)];
longPress.minimumPressDuration = 0;
[self addGestureRecognizer:longPress];
Run Code Online (Sandbox Code Playgroud)

然后我的tapAndSlide:方法:

- (void)tapAndSlide:(UILongPressGestureRecognizer*)gesture
{
    CGPoint pt = [gesture locationInView: self];
    CGFloat thumbWidth = [self thumbRect].size.width;
    CGFloat value;

    if(pt.x <= [self thumbRect].size.width/2.0)
        value = self.minimumValue;
    else if(pt.x >= self.bounds.size.width - thumbWidth/2.0)
        value = self.maximumValue;
    else {
        CGFloat percentage = (pt.x - thumbWidth/2.0)/(self.bounds.size.width - thumbWidth);
        CGFloat delta = percentage * (self.maximumValue - self.minimumValue);
        value = self.minimumValue + delta;
    }

    if(gesture.state == UIGestureRecognizerStateBegan){
        [UIView animateWithDuration:0.35 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            [self setValue:value animated:YES];
            [super sendActionsForControlEvents:UIControlEventValueChanged];
        } completion:nil];
    }
    else [self setValue:value];

    if(gesture.state == UIGestureRecognizerStateChanged)
        [super sendActionsForControlEvents:UIControlEventValueChanged];
}
Run Code Online (Sandbox Code Playgroud)

我还使用一种方法返回我的自定义thumbRect的框架:

- (CGRect)thumbRect {
    CGRect trackRect = [self trackRectForBounds:self.bounds];
    return [self thumbRectForBounds:self.bounds trackRect:trackRect value:self.value];
}
Run Code Online (Sandbox Code Playgroud)

我也让我的滑块动画显示用户首次点击的位置,超过0.35秒.我认为这看起来很甜蜜,所以我把它包含在那个代码中.如果您不想这样,只需尝试:

- (void)tapAndSlide:(UILongPressGestureRecognizer*)gesture
{
    CGPoint pt = [gesture locationInView: self];
    CGFloat thumbWidth = [self thumbRect].size.width;
    CGFloat value;

    if(pt.x <= [self thumbRect].size.width/2.0)
        value = self.minimumValue;
    else if(pt.x >= self.bounds.size.width - thumbWidth/2.0)
        value = self.maximumValue;
    else {
        CGFloat percentage = (pt.x - thumbWidth/2.0)/(self.bounds.size.width - thumbWidth);
        CGFloat delta = percentage * (self.maximumValue - self.minimumValue);
        value = self.minimumValue + delta;
    }

    [self setValue:value];

    if(gesture.state == UIGestureRecognizerStateChanged)
        [super sendActionsForControlEvents:UIControlEventValueChanged];
}
Run Code Online (Sandbox Code Playgroud)

我希望这是有道理的,并帮助你.


Jop*_*ped 13

我将DWilliames提供的答案转换为Swift

在你的viewDidAppear()里面

let longPress                  = UILongPressGestureRecognizer(target: self.slider, action: Selector("tapAndSlide:"))
longPress.minimumPressDuration = 0
self.addGestureRecognizer(longPress)
Run Code Online (Sandbox Code Playgroud)

类文件

class TapUISlider: UISlider
{
    func tapAndSlide(gesture: UILongPressGestureRecognizer)
    {
        let pt           = gesture.locationInView(self)
        let thumbWidth   = self.thumbRect().size.width
        var value: Float = 0

        if (pt.x <= self.thumbRect().size.width / 2)
        {
            value = self.minimumValue
        }
        else if (pt.x >= self.bounds.size.width - thumbWidth / 2)
        {
            value = self.maximumValue
        }
        else
        {
            let percentage = Float((pt.x - thumbWidth / 2) / (self.bounds.size.width - thumbWidth))
            let delta      = percentage * (self.maximumValue - self.minimumValue)

            value          = self.minimumValue + delta
        }

        if (gesture.state == UIGestureRecognizerState.Began)
        {
            UIView.animateWithDuration(0.35, delay: 0, options: UIViewAnimationOptions.CurveEaseInOut,
            animations:
            {
                self.setValue(value, animated: true)
                super.sendActionsForControlEvents(UIControlEvents.ValueChanged)
            },
            completion: nil)
        }
        else
        {
            self.setValue(value, animated: false)
        }
    }

    func thumbRect() -> CGRect
    {
        return self.thumbRectForBounds(self.bounds, trackRect: self.bounds, value: self.value)
    }
}
Run Code Online (Sandbox Code Playgroud)


Ali*_*bas 4

您应该在您的UISlider.

示例:

 UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sliderTapped:)];
    [_slider addGestureRecognizer:tapGestureRecognizer];
Run Code Online (Sandbox Code Playgroud)

在 sliderTapped 中,您可以获取位置并更新 slider 的值:

- (void)sliderTapped:(UIGestureRecognizer *)gestureRecognizer {
    CGPoint  pointTaped = [gestureRecognizer locationInView:gestureRecognizer.view];
    CGPoint positionOfSlider = _slider.frame.origin;
    float widthOfSlider = _slider.frame.size.width;
    float newValue = ((pointTaped.x - positionOfSlider.x) * _slider.maximumValue) / widthOfSlider;
    [_slider setValue:newValue];
}
Run Code Online (Sandbox Code Playgroud)

我在这里创建一个示例:https ://github.com/ali59a/tap-and-slide-in-a-UISlider