2009-11-11 65 views
26

我正在创建自定义UISlider以测试一些界面创意。主要基于使拇指图像变大。如何获得UISlider的拇指图像的中心

我发现了如何做到这一点,像这样:

UIImage *thumb = [UIImage imageNamed:@"newThumbImage_64px.png"]; 
[self.slider setThumbImage:thumb forState:UIControlStateNormal]; 
[self.slider setThumbImage:thumb forState:UIControlStateHighlighted]; 
[thumb release]; 

为了计算相关值,我需要知道在哪里,当它被操纵拇指图像的中心点下降。这点应该在它的超级观点的坐标中。

看着UISlider docs,我没有看到任何财产跟踪此。

是否有一些简单的方法来计算这个或者它是否可以从一些现有的值中派生出来?

回答

2

后IB和1px的宽拇指图像一点点打,拇指的位置正是你希望它:

UIImage  *thumb = [UIImage imageNamed:@"newThumbImage_64px.png"]; 
CGRect  sliderFrame = self.slider.frame; 
CGFloat  x = sliderFrame.origin.x + slideFrame.size.width * slider.value + thumb.size.width/2; 
CGFloat  y = sliderFrame.origin.y + sliderFrame.size.height/2; 

return CGPointMake(x, y); 
+0

假设滑块范围为0..1,当slider.value为0时,您的点是正确的,但滑块的值会更大。另外,x方程中有一个错字。 – willc2 2009-11-25 16:05:45

+0

此外,不应该sliderFrame.x be sliderFrame.origin.x&sliderFrame.size.width? – willc2 2009-11-25 16:09:04

+0

糟糕,关于错字,修复。 – 2009-11-25 18:12:09

53

这将返回拇指图像的中心的正确的X位置UISlider的视图坐标:

- (float)xPositionFromSliderValue:(UISlider *)aSlider { 
    float sliderRange = aSlider.frame.size.width - aSlider.currentThumbImage.size.width; 
    float sliderOrigin = aSlider.frame.origin.x + (aSlider.currentThumbImage.size.width/2.0); 

    float sliderValueToPixels = (((aSlider.value - aSlider.minimumValue)/(aSlider.maximumValue - aSlider.minimumValue)) * sliderRange) + sliderOrigin; 

    return sliderValueToPixels; 
} 

把它放在您的视图控制器,并使用它像这样:(假设为Slider属性)

float x = [self xPositionFromSliderValue:self.slider]; 
+3

这适用于我,除了需要一个更改以允许具有自定义最小/最大值的滑块: float sliderValueToPixels =(aSlider.value/aSlider.maximumValue * sliderRange)+ sliderOrigin; 此外,它被这样调用: float x = [self xPositionFromSliderValue:someSlider]; – 2010-03-24 20:41:48

+0

完美结合James的修改 – 2011-08-18 12:17:03

+7

实际上,为了适应不是0(或接近它)的自定义最小值,您需要将其更改为:float sliderValueToPixels =((((aSlider.value-aSlider.minimumValue )/(aSlider.maximumValue-aSlider.minimumValue))* sliderRange)+ sliderOrigin; – Joel 2012-03-07 04:23:24

6

我通过首先映射UISlider的值间隔百分比,然后采用相同百分比的滑块大小减去拇指大小的百分比来获得它,这是我将拇指大小的一半加到其中心的值。

- (float)mapValueInIntervalInPercents: (float)value min: (float)minimum max: (float)maximum 
    { 
     return (100/(maximum - minimum)) * value - 
       (100 * minimum)/(maximum - minimum); 
    }  


    - (float)xPositionFromSliderValue:(UISlider *)aSlider 
    { 
     float percent = [self mapValueInIntervalInPercents: aSlider.value 
           min: aSlider.minimumValue 
           max: aSlider.maximumValue]/100.0; 

     return percent * aSlider.frame.size.width - 
       percent * aSlider.currentThumbImage.size.width + 
       aSlider.currentThumbImage.size.width/2; 
    } 
12

我想知道为什么没有人提供最简单的答案,其中包括阅读手册。您可以准确,也计算所有这些值,确保他们保持这种方式,通过简单的使用方法:

- (CGRect)trackRectForBounds:(CGRect)bounds 
- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value 

,你可以很容易地找到开发者文档。

如果拇指图像发生变化,并且您想要更改其定位方式,则您可以继承并覆盖这些方法。第一个给你的拇指可以移动第二个拇指本身的位置的矩形。

+1

这是定义的答案!只需更新一个包含[super trackRectForBounds]返回值的成员变量,就可以跳过所有的计算。优秀! – Krumelur 2012-03-18 09:36:11

+6

这两种方法的文档说明:“你不应该直接调用这个方法。” – 2013-03-21 17:39:04

+1

@IgorKulagin你不需要直接打电话给他们...... – Beppe 2013-08-17 15:48:20

18

这个我试过看完上面的建议后 -

yourLabel = [[UILabel alloc]initWithFrame:....]; 

//Call this method on Slider value change event 

-(void)sliderValueChanged{ 
    CGRect trackRect = [self.slider trackRectForBounds:self.slider.bounds]; 
    CGRect thumbRect = [self.slider thumbRectForBounds:self.slider.bounds 
           trackRect:trackRect 
            value:self.slider.value]; 

    yourLabel.center = CGPointMake(thumbRect.origin.x + self.slider.frame.origin.x, self.slider.frame.origin.y - 20); 
} 

我可以用这个片段中得到最准确的值。

0

以上解决方案在UISlider水平时非常有用。在最近的一个项目中,我们需要用角度来使用UISlider。所以我需要获得x和y的位置。使用以下来计算X,Y轴:

- (CGPoint)xyPositionFromSliderValue:(UISlider *)aSlider WithAngle:(double)aangle{ 
    //aangle means the dextrorotation angle compare to horizontal. 
    float xOrigin = 0.0; 
    float yOrigin = 0.0; 
    float xValueToaXis=0.0; 
    float yValueToaXis=0.0; 
    float sliderRange = slider_width-aSlider.currentThumbImage.size.width; 
    xOrigin = aSlider.frame.origin.x+slider_width*fabs(cos(aangle/180.0*M_PI)); 
    yOrigin = aSlider.frame.origin.y; 

    xValueToaXis = xOrigin + ((((((aSlider.value-aSlider.minimumValue)/(aSlider.maximumValue-aSlider.minimumValue)) * sliderRange))+(aSlider.currentThumbImage.size.width/2.0))*cos(aangle/180.0*M_PI)) ; 
    yValueToaXis = yOrigin + ((((((aSlider.value-aSlider.minimumValue)/(aSlider.maximumValue-aSlider.minimumValue)) * sliderRange))+(aSlider.currentThumbImage.size.width/2.0))*sin(aangle/180.0*M_PI)); 

    CGPoint xyPoint=CGPointMake(xValueToaXis, yValueToaXis); 
    return xyPoint; 
} 

此外,我可以创建基于UISlider游侠滑块?谢谢。

10

最好使用-[UIView convertRect:fromView:]方法代替。它的清洁和更容易没有任何复杂的计算:

- (IBAction)scrub:(UISlider *)sender 
{ 
    CGRect _thumbRect = [sender thumbRectForBounds:sender.bounds 
             trackRect:[sender trackRectForBounds:sender.bounds] 
              value:sender.value]; 
    CGRect thumbRect = [self.view convertRect:_thumbRect fromView:sender]; 

    // Use the rect to display a popover (pre iOS 8 code) 
    [self.popover dismissPopoverAnimated:NO]; 
    self.popover = [[UIPopoverController alloc] initWithContentViewController:[UIViewController new]]; 
    [self.popover presentPopoverFromRect:thumbRect inView:self.view 
       permittedArrowDirections:UIPopoverArrowDirectionDown|UIPopoverArrowDirectionUp animated:YES]; 
} 
+2

这是一个明确的答案。无需分类UISlider。谢谢你 – klefevre 2014-08-31 23:08:44

+0

是的,这是正确的答案。 – 2017-07-16 10:38:53

1

这里是一个雨燕2.2的解决方案,我创建了它的扩展。我只使用默认图像尝试了这一点。

import UIKit 

extension UISlider { 

    var thumbImageCenterX: CGFloat { 
     let trackRect = trackRectForBounds(bounds) 
     let thumbRect = thumbRectForBounds(bounds, trackRect: trackRect, value: value) 

     return thumbRect.origin.x + thumbRect.width/2 - frame.size.width/2 
    } 
} 
+0

谢谢! :) !! – 2016-09-21 07:58:57

11

斯威夫特3

extension UISlider { 
    var thumbCenterX: CGFloat { 
     let trackRect = self.trackRect(forBounds: frame) 
     let thumbRect = self.thumbRect(forBounds: bounds, trackRect: trackRect, value: value) 
     return thumbRect.midX 
    } 
} 
0

这将为UISlider工作在任何地方被放置在屏幕上。大多数其他解决方案只有在UISlider与屏幕左边缘对齐时才会起作用。请注意,我使用了frame而不是bounds作为thumbRect,来实现这一点。我表现出两种变化,基于使用framebounds为trackRect

extension UISlider { 

    //this version will return the x coordinate in relation to the UISlider frame 
    var thumbCenterX: CGFloat { 
     return thumbRect(forBounds: frame, trackRect: trackRect(forBounds: bounds), value: value).midX 
    } 

    //this version will return the x coordinate in relation to the UISlider's containing view 
    var thumbCenterX: CGFloat { 
     return thumbRect(forBounds: frame, trackRect: trackRect(forBounds: frame), value: value).midX 
    } 

} 
1

雨燕3.0
如果你喜欢,请参考。

import UIKit 

extension UISlider { 

    var trackBounds: CGRect { 
     return trackRect(forBounds: bounds) 
    } 

    var trackFrame: CGRect { 
     guard let superView = superview else { return CGRect.zero } 
     return self.convert(trackBounds, to: superView) 
    } 

    var thumbBounds: CGRect { 
     return thumbRect(forBounds: frame, trackRect: trackBounds, value: value) 
    } 

    var thumbFrame: CGRect { 
     return thumbRect(forBounds: bounds, trackRect: trackFrame, value: value) 
    } 
}