37

我正在创建一个自定义UISlider来测试一些界面创意。主要基于使拇指图像更大。

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

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

要计算相关值,我需要知道拇指图像的中心点在被操作时落在哪里。并且该点应该在它的超级视图的坐标中。

查看UISlider文档,我没有看到任何跟踪此内容的属性。

有没有一些简单的方法来计算这个,或者它可以从一些现有的值中推导出来?

4

12 回答 12

60

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

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

将它放在您的视图控制器中并像这样使用它:(假设属性名为滑块)

float x = [self xPositionFromSliderValue:self.slider];
于 2009-11-26T16:42:44.907 回答
25

在阅读了上述建议后,我尝试了这个 -

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

对于Swift 版本

func sliderValueChanged() -> Void {
        let trackRect =  self.slider.trackRect(forBounds: self.slider.bounds)
        let thumbRect = self.slider.thumbRect(forBounds: self.slider.bounds, trackRect: trackRect, value: self.slider.value)
        yourLabel.center = CGPoint(x: thumbRect.origin.x + self.slider.frame.origin.x + 30, y: self.slider.frame.origin.y - 60)
    }

通过使用此代码段,我可以获得最准确的值。

于 2012-09-26T11:12:07.793 回答
22

斯威夫特 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
    }
}
于 2016-09-20T19:30:56.083 回答
11

我想知道为什么你们都没有提供最简单的答案,即阅读手册。您可以准确地计算所有这些值,并确保它们保持不变,只需使用以下方法:

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

您可以在开发人员文档中轻松找到它。

如果拇指图像发生变化并且您想更改它的定位方式,则子类化并覆盖这些方法。第一个为您提供拇指可以移动的矩形,第二个为拇指本身的位置。

于 2010-10-15T12:32:48.730 回答
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];
}
于 2013-12-01T22:54:50.197 回答
7

我通过首先以百分比映射 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;
    }
于 2009-12-15T19:04:35.007 回答
3

Swift 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)
    }
}
于 2017-07-10T09:30:42.097 回答
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);
于 2009-11-19T13:25:38.007 回答
1

这是一个 Swift 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
    }
}
于 2016-08-31T04:49:51.947 回答
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 创建 Ranger Slider 吗?谢谢。

于 2013-04-08T01:50:14.057 回答
0

这适用于将 UISlider 放置在屏幕上的任何位置。大多数其他解决方案仅在 UISlider 与屏幕左边缘对齐时才有效。请注意,我使用frame而不是boundsthumbRect 来实现这一点。我展示了两种变体,基于使用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
    }

}
于 2017-04-22T17:06:51.927 回答
0

第 1 步:获取检测位置的视图(使用与#Ovi Bortas 相同的扩展顶部commet)

@IBOutlet 弱变量滑块视图:UIView!

第 2 步:为添加子视图设置标签框架 func setLabelThumb(slider:UISlider,value:Float){ slider.value = value

let label = UILabel(frame:  CGRect(x: slider.thumbCenterX - 20, y: slider.frame.origin.y - 25, width: 50, height: 30))
label.font = UIFont.systemFont(ofSize: 10.0)
label.textColor = UIColor.red
label.textAlignment = .center
label.text = "\(value) kg."

sliderView.addSubview(label)

}

于 2019-09-20T04:36:15.827 回答