自定义UISlider - 增加“热点”大小

时间:2012-11-02 13:32:49

标签: objective-c ios uislider

我有一个定制的UISlider,对于大手指的人来说,由于“拇指图像”的大小而难以抓住并滑动。有没有办法在不改变图像大小的情况下增加可点击/可拖动区域的大小?

以下是我创建自定义滑块的代码,如果有帮助的话:

[slider setMaximumTrackImage:[[UIImage imageNamed:@"max.png"]
                                             resizableImageWithCapInsets:UIEdgeInsetsMake(0, 20, 0, 20)]
                                   forState:UIControlStateNormal];
[slider setMinimumTrackImage:[[UIImage imageNamed:@"min.png"]
                                             resizableImageWithCapInsets:UIEdgeInsetsMake(0, 20, 0, 20)]
                                   forState:UIControlStateNormal];
[slider setThumbImage:[UIImage imageNamed:@"thumb.png"]
                            forState:UIControlStateNormal];

7 个答案:

答案 0 :(得分:26)

我最终继承了UISlider并重写了这个方法:

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

这使得可触摸区域在左侧和右侧延伸了10个像素,在顶部和底部延伸了15个像素。

答案 1 :(得分:7)

此解决方案适用于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))
    }
}

致记此帖:http://www.mpatric.com/2009-04-15-more-responsive-sliders-on-the-iphone

答案 2 :(得分:6)

Swift 3

触摸面积增加的UISlider的子类

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)
    }
}

答案 3 :(得分:2)

答案 4 :(得分:1)

我最终使用了它,它对我来说效果很好。

发布此答案,以便对某人有所帮助。

# the main menu boostrap like
lib.navBarMenu = HMENU
lib.navBarMenu {
    1 = TMENU
    1 {
        # accessibility - add title for main navigation
        wrap (
            <h2 class="sr-only">{$TEXT.titleMainnav}</h2>
            <ul class="nav navbar-nav" id="nav">|</ul>
        )

        # Always unfold all sub-levels of the menu
        expAll = 1

        # Remove the (old) default behaviour which adds onfocus="blurLink(this);" to all links
        noBlur = 1

        # Define the normal state (not active, not selected) of menu items
        # Using NO=1 to activate normal state is not necessary, but useful when copying
        NO = 1
        NO {
            # Use the page title field as title property in the A-tag, and if the navigation title is set, take the value of this field
            ATagTitle {
                field = title
                stdWrap.override.cObject = TEXT
                stdWrap.override.cObject.field = nav_title
                stdWrap.override.if.isTrue.field = nav_title
            }

            # Use the option-split feature to generate a different wrap for the last item on a level of the menu
            # The last item on each level gets class="last" added for CSS styling purposes.
            #
            # See the TSref documentation for details about option split and other features:
            # http://typo3.org/documentation/document-library/references/doc_core_tsref/current/
            #wrapItemAndSub = <li class="first">|</li> |*| <li>|</li> |*| <li class="last">|</li>
            wrapItemAndSub = <li>|</li>

            # HTML-encode special characters according to the PHP-function htmlSpecialChars
            stdWrap.htmlSpecialChars = 1
        }

        IFSUB = 1
        IFSUB < .NO
        IFSUB {
            wrapItemAndSub = <li class="dropdown">|</li>                 
            ATagBeforeWrap = 1
            ATagParams = class="dropdown-toggle" data-toggle="dropdown"
            stdWrap.wrap = |<b class="caret"></b>
        }

        # Copy properties of normal to active state, and then add a CSS class for styling
        ACTIFSUB = 1
        ACTIFSUB < .IFSUB
        ACTIFSUB {
            wrapItemAndSub = <li class="dropdown active">|</li>
        }

        CURIFSUB = 1
        CURIFSUB < .IFSUB
        CURIFSUB {
            wrapItemAndSub = <li class="dropdown active">|</li>
        }

        # Copy properties of normal to active state, and then add a CSS class for styling
        ACT = 1
        ACT < .NO
        ACT {
            wrapItemAndSub = <li class="active">|</li>
        }

        # Copy properties of normal to current state, and then add a CSS class for styling
        CUR = 1
        CUR < .NO
        CUR {
            wrapItemAndSub = <li class="active">|</li>
        }
    }
    2 < .1
    2 {
        wrap = <ul class="dropdown-menu">|</ul>
        IFSUB {
            wrapItemAndSub = <li class="dropdown-submenu">|</li>
            ATagParams >
            stdWrap.wrap >
        }

        ACTIFSUB {
            wrapItemAndSub = <li class="dropdown-submenu">|</li>
            ATagParams >
            stdWrap.wrap >
        }

        CURIFSUB {
            wrapItemAndSub = <li class="dropdown-submenu">|</li>
            ATagParams >
            stdWrap.wrap >
        }
    }
    3 < .2
    4 < .2
    5 < .2
    6 < .2
    7 < .2
}

答案 5 :(得分:1)

另外,您可以只提取图像尺寸,这会导致滑块拇指尺寸增加。

  1. 如果您需要保持图像尺寸不要太大但调整滑块尺寸,只需在图像内容周围添加透明空间即可。 enter image description here

  2. 如果您在UITableViewCell中使用滑块,问题还在于tableview处理手势滑块之前。要更改此,请使用以下解决方案: https://stackoverflow.com/a/37751635/2150954 我认为将他的代码翻译成Objective C并不太难。

答案 6 :(得分:-1)

调整框架大小并将图像对齐方式更改为所需的对齐方式。您可以使其对齐居中,左,右,顶部或底部。这样做:

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

因此,您的触摸框架会更大,图像比例将保持不变。