3

I have multiple controllers in my PageViewController and in one controller I have a few sliders. Now there is a problem that user must touch exactly slider circle (I am not sure about right expression, thumb? - that moving part) and I would like to increase area in which reacts slider and not the whole PageViewController. I tried these solutions but it doesn't help:

  • thumbRectForBounds:

    - (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value
    {
        return CGRectInset ([super thumbRectForBounds:bounds trackRect:rect value:value], 15, 15);
    }
    
  • Increase hitTest area:

    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
        if (CGRectContainsPoint(CGRectInset(self.frame, 200, 200), point) || CGRectContainsPoint(CGRectInset(self.frame, 200, 200), point)) {
             return self;
        }
        return [super hitTest:point withEvent:event];
    }
    

I have these methods in my custom slider class because I would like to reuse this. Last thing what I found and not tried yet is create some object layer over slider which "takes" gesture and disable PageViewController but I am not sure how to do it and I am not sure if it's good/best solution.

Libor Zapletal
  • 13,752
  • 20
  • 95
  • 182

3 Answers3

2

I am not a big fan of the UISlider component because as you noticed, it is not trivial to increase the hit area of the actual slider. I would urge you to replicate the UISlider instead using a pan gesture for a much better user experience:

i. create a slider background with a seperate UIImageView with a slider image. ii. create the PanGesture:

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:);
[imageView addGestureRecognizer:pan];

iii. implement handlePan Method:

- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {

    //pan (slide) begins
    CGPoint translation = [recognizer locationInView:self.view];
    translation.y = self.slideImage.center.y;
    self.slideImage.center = translation;

    if(recognizer.state == UIGestureRecognizerStateEnded) {
        LTDebugLog(@"\n\n PAN, with spot: %f\n\n", self.slideImage.center.x);
        //do something after user is done sliding
    }
}

The big benefit of this method is that you will have a much better user experience as you can make the responsive UIImageView as big as you want.

Alternatively, you could subclass a UISlider and increase the hit space there, although in my experience this gives mixed results.

Hope this helps

trdavidson
  • 1,051
  • 12
  • 25
1

In your CustomSlider class override thumbRectForBounds method:

Simply return rect value as you required:

- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value
{
    return CGRectMake (bounds.origin.x, bounds.origin.y, yourWidthValue, yourHeightValue );
}

Change yourWidthValue and yourHeightValue as per your requirement. And then while using

Create object like below:

CustomSlider *slider  = [[CustomSlider alloc] initWithFrame:CGRectMake(0, 0, 300, 20)];
[slider thumbRectForBounds: slider.bounds trackRect:slider.frame value:15.f]; // change values as per your requirements.

Hope this helps.

Mrunal
  • 13,982
  • 6
  • 52
  • 96
  • This is what I was trying to do in first aproach. I just used CGRectInset because it works better in this. But when I set in my example values to bigger than 15 then thumb is missing. And this method is override so call it after init of control it doesn't help, right? It doesn't set anything and you just don't use CGRect which returns. – Libor Zapletal Dec 24 '14 at 11:37
1

Create a custom thumb image which has a large empty margin and set that on your slider, like this:

[theSlider setThumbImage:[UIImage imageNamed:@"slider_thumb_with_margins"] forState:UIControlStateNormal];

To make the image, get a copy of the system thumb image using any one of a number of UIKit artwork extractors (just search the web for one). Open the thumb image in Photoshop and increase the canvas size by twice the margin you want to add. Make sure you change the canvas size and not the image size, as the image size will stretch the image to fill the new size. This will put empty space around the thumb which will be part of the hit-test area but since it is all transparent it won't change the look of the slider.

John Stephen
  • 7,625
  • 2
  • 31
  • 45