如何启用“点按和滑动”按钮在UISlider? [英] How to enable "tap and slide" in a UISlider?

查看:263
本文介绍了如何启用“点按和滑动”按钮在UISlider?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要的是一个 UISlider ,它让用户不仅可以在 thumbRect 上启动时滑动,当他在其他地方轻拍时。当用户点击滑块但在 thumbRect 之外时,滑块应跳转到该值,然后仍然保持用户的滑动手势



到目前为止,我所尝试的是实现了一个UIGestureRecognizer的子类,如 in这个建议。它会在 thumbRect 之外的某处触发时启动。问题是滑块设置其值,但是由于触摸识别器已经触摸了,因此忽略了进一步的滑动手势。



怎么能我实现了一个滑块,您可以在任何地方点按,但仍然可以立即滑动?






编辑:ali59a非常友好地添加< a href =https://stackoverflow.com/a/22718266/176248>我现在所做的一个例子。这需要再次抬起手指,然后我可以触摸并拖动滑动(水龙头不是我想要的,我需要立即'触摸和滑动'。)

解决方案

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



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



只需更换 UITapGestureRecognizer ,带有 UILongPressGestureRecognizer 。但是,我发现这似乎并没有将thumbRect直接放在我的拇指下面。它对我来说有点不对。



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

在我的 init 方法中:

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

然后我的 tapAndSlide:方法:

   - (void)tapAndSlide:(UILongPressGestureRecognizer *)手势
{
CGPoint pt = [手势locationInView:self ]。
CGFloat thumbWidth = [self thumbRect] .size.width;
CGFloat值;

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 =百分比*(self.maximumValue - self.minimumValue);
value = self.minimumValue + delta;
}

if(gesture.state == UIGestureRecognizerStateBegan){
[UIView animateWithDuration:0.35 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^ {
[self setValue:值动画:是];
[super sendActionsForControlEvents:UIControlEventValueChanged];
}完成:nil];
}
else [self setValue:value];

if(gesture.state == UIGestureRecognizerStateChanged)
[super sendActionsForControlEvents:UIControlEventValueChanged];
}

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

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

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

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

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 =百分比*(self.maximumValue - self.minimumValue);
value = self.minimumValue + delta;
}

[self setValue:value];

if(gesture.state == UIGestureRecognizerStateChanged)
[super sendActionsForControlEvents:UIControlEventValueChanged];
}

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


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 taps on the slider but outside of the thumbRect, the slider should jump to that value and then still keeping up to the user's sliding gesture.

What I have tried so far was implementing a subclass of UIGestureRecognizer like in this suggestion. It starts right then when a touch down somewhere outside the thumbRect occurs. The problem is that the slider sets its value but then further sliding gestures are ignored because the touch down recognizer has stolen the touch.

How can I implement a slider where you can tap anywhere but still slide right away?


Edit: ali59a was so kind to add an example of what I've done now. This requires to lift the finger again, after that I can touch and drag to slide (a tap is not what I want, I need a 'touch and slide' right away).

解决方案

I'm not sure if you are still looking for an answer for this, but I was just looking at this myself today; and I managed to get it to work for me.

The key to it, is using a UILongPressGestureRecognizer instead of just a UITapGestureRecognizer, we can then set the minimumPressDuration of the recognizer to 0; making it act as a tap recognizer, except you can now actually check its state.

Putting what ali59a suggested will work for you, just by replacing the UITapGestureRecognizer with a UILongPressGestureRecognizer. However, I found that this didn't seem to quite put the thumbRect directly under my thumb. It appeared a bit off to me.

I created my own UISlider subclass for my project, and here is how I implemented the "tap and slide feature" for me.

In my init method:

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

Then my tapAndSlide: method:

- (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];
}

Where I also used a method to return the frame of my custom thumbRect:

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

I also have my slider animate to the position where the user first taps, over 0.35 seconds. Which I reckon looks pretty sweet, so I included that in that code. If you don't want that, simply try this:

- (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];
}

I hope that makes sense, and helps you.

这篇关于如何启用“点按和滑动”按钮在UISlider?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆