Custom UISlider - Increase “hot spot” size

前端 未结 6 740
时光说笑
时光说笑 2020-12-08 08:21

I have a custom UISlider that is relatively tough for big fingered people to grab hold of and slide due to the size of the \"thumb image\". Is there any way to increase the

相关标签:
6条回答
  • 2020-12-08 08:55

    This solution works with iOS 8:

    class ExtUISlider: UISlider {
    
        var thumbTouchSize : CGSize = CGSizeMake(50, 50)
    
        override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
            let bounds = CGRectInset(self.bounds, -thumbTouchSize.width, -thumbTouchSize.height);
            return CGRectContainsPoint(bounds, point);
        }
    
        override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool {
            let thumbPercent = (value - minimumValue) / (maximumValue - minimumValue)
            let thumbSize = thumbImageForState(UIControlState.Normal)!.size.height
            let thumbPos = CGFloat(thumbSize) + (CGFloat(thumbPercent) * (CGFloat(bounds.size.width) - (2 * CGFloat(thumbSize))))
            let touchPoint = touch.locationInView(self)
    
            return (touchPoint.x >= (thumbPos - thumbTouchSize.width) &&
                touchPoint.x <= (thumbPos + thumbTouchSize.width))
        }
    }
    

    Credits go to this post: http://www.mpatric.com/2009-04-15-more-responsive-sliders-on-the-iphone

    0 讨论(0)
  • 2020-12-08 08:55

    Also you can just increese image size which will lead to increasing of slider thumb size.

    1. If you need to left image size not too big but adjust slider size just add transparent space around image content.

    2. If you are using slider in UITableViewCell the problem also is that tableview handle gesture just before the slider. To change this use the following solution: https://stackoverflow.com/a/37751635/2150954 I think it is not too difficult to translate his code to Objective C.

    0 讨论(0)
  • 2020-12-08 09:00

    Swift 3

    Subclass of UISlider with increased touch area

    class CustomSlider: UISlider {
    
        private var thumbTouchSize = CGSize(width: 40, height: 40)
    
        override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
            let increasedBounds = bounds.insetBy(dx: -thumbTouchSize.width, dy: -thumbTouchSize.height)
            let containsPoint = increasedBounds.contains(point)
            return containsPoint
        }
    
        override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
            let percentage = CGFloat((value - minimumValue) / (maximumValue - minimumValue))
            let thumbSizeHeight = thumbRect(forBounds: bounds, trackRect:trackRect(forBounds: bounds), value:0).size.height
            let thumbPosition = thumbSizeHeight + (percentage * (bounds.size.width - (2 * thumbSizeHeight)))
            let touchLocation = touch.location(in: self)
            return touchLocation.x <= (thumbPosition + thumbTouchSize.width) && touchLocation.x >= (thumbPosition - thumbTouchSize.width)
        }
    }
    
    0 讨论(0)
  • 2020-12-08 09:10

    I ended up subclassing the UISlider and overriding this method:

    - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
        CGRect bounds = self.bounds;
        bounds = CGRectInset(bounds, -10, -15);
        return CGRectContainsPoint(bounds, point);
    }
    

    This extends the touchable area by 10 pixels on the left and right and 15 pixels on the top and bottom.

    0 讨论(0)
  • 2020-12-08 09:10

    I ended up using this and it works pretty well for me.

    Posted this answer, so that it could be helpful to someone.

    import UIKit
    
    class CustomSlider: UISlider {
    
    /*
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
    }
    */
    // Increase slider height
       override func trackRect(forBounds bounds: CGRect) -> CGRect {
        let customBounds: CGRect = CGRect(origin: bounds.origin, size: CGSize(width: bounds.size.width, height: 5.0))
        return customBounds
    }
    
    
    
    override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect {
        return super.thumbRect(
            forBounds: bounds, trackRect: rect, value: value)
    
    
    }
    
    // Increase Thumb hot spot clickable area
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        var bounds: CGRect = self.bounds
        bounds = bounds.insetBy(dx: -10, dy: -10);
        return bounds.contains(point);
    
    }
    
    override func awakeFromNib() {
        // Configure Volume slider
        let thumbImageNormal = UIImage.init(named:"thumb")
        self.setThumbImage(thumbImageNormal, for: .normal)
    
        super.awakeFromNib()
    }
    
    }
    
    0 讨论(0)
  • 2020-12-08 09:15

    Resize frame and change image alignment to desired one. You can make its alignment centred, left, right, top or bottom. Make it this way:

    CGRect newFrame = sliderHandle.frame;
    CGRectSetWidth(newFrame, 80);
    CGRectSetHeight(newFrame, 80);
    [sliderHandle setFrame:newFrame];
    [sliderHandle setContentMode:UIViewContentModeCenter];
    

    So your touching frame will be bigger and image scale will remain unchanged.

    0 讨论(0)
提交回复
热议问题