简体   繁体   English

是否可以向 UISlider 的拇指图像添加标签?

[英]Is that possible to add a label to the UISlider's thumb image?

I want to add a label to the slider's thumb which should show the value of the slider and changes too when thumbs is being dragged towards right side.我想为滑块的拇指添加一个标签,该标签应该显示滑块的值,并且在将拇指拖向右侧时也会发生变化。 Is it possible??是否可以??

Any comments or suggestion would be appreciated.任何意见或建议将不胜感激。

I grab the thumb image from the slider (UIImageView) and add my label to it.我从滑块 (UIImageView) 中抓取拇指图像并将我的标签添加到它。 Nice and clean.漂亮干净。

UIImageView *handleView = [slider.subviews lastObject];
UILabel *label = [[UILabel alloc] initWithFrame:handleView.bounds];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
[handleView addSubview:label];
self.sliderLabel = label;

Then you change the label.text whenever you need to.然后您可以随时更改 label.text 。

Note: the subview order of UISlider could change in the future, however it's unlikely that the thumb would no longer be the topmost view, as it will always be the main point of interaction in a slider.注意:UISlider 的子视图顺序将来可能会改变,但是拇指不太可能不再是最顶层的视图,因为它始终是滑块中交互的主要点。

Swift 3 -- More detailed example (link your slider in IB) Swift 3 -- 更详细的示例(在 IB 中链接您的滑块)

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var slider: UISlider!
    var sliderLabel: UILabel?

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        if let handleView = slider.subviews.last as? UIImageView {
            let label = UILabel(frame: handleView.bounds)
            label.backgroundColor = .clear
            label.textAlignment = .center
            handleView.addSubview(label)

            self.sliderLabel = label
            //set label font, size, color, etc.
            label.text = "!!"
        }
    }
}

You could do something similar to this example which draws text directly to your thumb image.您可以执行类似于此示例的操作,将文本直接绘制到拇指图像。 It's a rough example so you will need to change it to make sense for your project.这是一个粗略的示例,因此您需要对其进行更改以使其对您的项目有意义。

- (IBAction)sliderValueChanged:(id)sender {
    UISlider *aSlider = (UISlider *)sender;
    NSString *strForThumbImage = 
     [NSString stringWithFormat:@"%.0f", aSlider.value * 100]
    UIImage *thumbImage = [self addText:self.thumbImage 
                                   text:strForThumbImage];
    [aSlider setThumbImage:thumbImage forState:aSlider.state];
}

//Add text to UIImage 
-(UIImage *)addText:(UIImage *)img text:(NSString *)text1{ 
    int w = img.size.width; 
    int h = img.size.height; 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate( NULL, 
                                                  w, 
                                                  h, 
                                                  8, 
                                                  4 * w, 
                                                  colorSpace, 
                                                  kCGImageAlphaPremultipliedFirst); 
    CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage); 

    char* text= (char *)[text1 cStringUsingEncoding:NSASCIIStringEncoding]; 
    CGContextSelectFont(context, "Arial",12, kCGEncodingMacRoman); 
    CGContextSetTextDrawingMode(context, kCGTextFill); 
    CGContextSetRGBFillColor(context, 0, 0, 0, 1); 
    CGContextShowTextAtPoint(context,3,8,text, strlen(text)); 
    CGImageRef imgCombined = CGBitmapContextCreateImage(context); 

    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 

    UIImage *retImage = [UIImage imageWithCGImage:imgCombined]; 
    CGImageRelease(imgCombined); 

    return retImage; 
}

A simple implementation of a custom class in Swift 3.2. Swift 3.2 中自定义类的简单实现。 This is working nicely for me.这对我来说很好用。

class ThumbTextSlider: UISlider {
var thumbTextLabel: UILabel = UILabel()

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

override func layoutSubviews() {
    super.layoutSubviews()

    thumbTextLabel.frame = thumbFrame
    thumbTextLabel.text = Double(value).roundTo(places: 1).description
}

override func awakeFromNib() {
    super.awakeFromNib()
    addSubview(thumbTextLabel)
    thumbTextLabel.textAlignment = .center
    thumbTextLabel.layer.zPosition = layer.zPosition + 1
}
}

I hope it helps :)我希望它有帮助:)

Add a UISlider and a UILabel in Interface Builder.在 Interface Builder 中添加一个UISlider和一个UILabel Create IBOutlets to access them in code and add a IBAction to respond to changes of the slider value.创建 IBOutlets 以在代码中访问它们并添加 IBAction 以响应滑块值的更改。

Then in your code write:然后在你的代码中写:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self.slider addSubview:self.label];
    [self valueChanged:self.slider];
}

- (IBAction)valueChanged:(id)sender {
    self.label.center = CGPointMake(self.slider.value*self.slider.bounds.size.width, 40);
    self.label.text = [NSString stringWithFormat:@"%0.2f", self.slider.value];
}

EDIT: To create the slider and label with code add this:编辑:要使用代码创建滑块和标签,请添加以下内容:

-(void)loadView {
    [super loadView];
    self.slider = [[[UISlider alloc] initWithFrame:CGRectMake(50, 150, 200, 30)] autorelease];
    self.label = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 30)] autorelease];
    [self.label setBackgroundColor:[UIColor clearColor]];
    [self.slider addTarget:self action:@selector(valueChanged:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview:self.slider];

}

You can access the rect for the slider's thumb image view with -thumbRectForBounds:trackRect:value:] , so if you add a UILabel subview you can align it relative to the thumb image view in -layoutSubviews using this returned rect.您可以使用-thumbRectForBounds:trackRect:value:]访问滑块的拇指图像视图的矩形,因此如果您添加UILabel子视图,您可以使用此返回的矩形将其与-layoutSubviews的拇指图像视图对齐。

However, if you'd like to use Autolayout to align your label with the thumb image then you need access to the thumb's UIImageView directly.但是,如果您想使用 Autolayout 将标签与拇指图像对齐,那么您需要直接访问拇指的UIImageView I'm not keen on spelunking the subviews of UIKit kit components generally, but I think you can use details of the public API to search for the image view in a future-proofed way:我一般不热衷于探索UIKit套件组件的子视图,但我认为您可以使用公共 API 的详细信息以面向未来的方式搜索图像视图:

- (UIImageView*) thumbImageView {
    __block UIImageView *imageView = nil;
    [self.subviews enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(UIImageView *candidate, NSUInteger idx, BOOL *stop)
    {
        if ([candidate isKindOfClass:[UIImageView class]] && candidate.image ==
                [self thumbImageForState:UIControlStateNormal])
        {
            imageView = candidate;
            *stop = YES;
        }
    }];
    return imageView;
}

The API provides the ability to set a UIImage for the thumb, so you can use this as a test to ensure that you aren't getting some other image view. API 提供了为拇指设置UIImage的功能,因此您可以将其用作测试以确保您没有获得其他图像视图。 This is even safer if you are explicitly setting a thumb image yourself (since it's not impossible that the slider might be changed to draw the thumb image in future...).这是更安全,如果您明确设置自己的拇指图像(因为这不是不可能的滑块可能会更改为绘制拇指图像中的未来......)。 Also, the thumb image view is currently the last subview (not guaranteed going forward), so I'm doing a reverse enumeration here to hopefully get it as faster as possible whilst not making assumptions about its index.此外,拇指图像视图目前是最后一个子视图(不保证向前),所以我在这里做一个反向枚举,希望尽可能快地得到它,同时不对其索引做出假设。

NB: I had to create my thumb label lazily, since UISlider 's subviews seem to be so.注意:我不得不懒惰地创建我的拇指标签,因为UISlider的子视图似乎是这样。

make this nice and easy.. first off this is the final result让这一切变得美好而简单……首先这是最终结果

在此处输入图片说明

and now, code:现在,代码:

UILabel *sl = [UILabel new];
[v addSubview:sl];
[sl constraintHeightEqualTo:12 widthTo:26];
UIImageView *handleView = [slider.subviews lastObject];

[self.view constraintVerticalSpacingSubviewsFromBottomView:s toTopView:sl constant:10];
[self.view constraintCenterXOfView:sl equalToView:handleView];
[sl setText:@"100%"];
[sl setFont:[UIFont systemFontOfSize:10]];
self.sliderLabel = sl;

the above methods are used from an NSLayoutConstraint category i use (coming soon)上述方法来自我使用的NSLayoutConstraint类别(即将推出)

- (id)constraintHeightEqualTo:(CGFloat)height widthTo:(CGFloat)width
{
    [self setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self constraintHeightEqualTo:height];
    [self constraintWidthEqualTo:width];
    return self;
}
- (id)constraintVerticalSpacingSubviewsFromBottomView:(UIView *)fromView toTopView:(UIView *)toView constant:(CGFloat)constant

{
    NSLayoutConstraint *cn = [NSLayoutConstraint constraintWithItem:fromView
                                                          attribute:NSLayoutAttributeTop
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:toView
                                                          attribute:NSLayoutAttributeBottom
                                                         multiplier:1
                                                           constant:constant];
    [self addConstraint:cn];
    return self;
}

- (id)constraintCenterXOfView:(UIView *)fromView equalToView:(UIView *)toView constant:(CGFloat)constant
{
    NSLayoutConstraint *cn = [NSLayoutConstraint constraintWithItem:fromView
                                                          attribute:NSLayoutAttributeCenterX
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:toView
                                                          attribute:NSLayoutAttributeCenterX
                                                         multiplier:1 constant:constant];

    [self addConstraint:cn];
    return self;
}
- (IBAction)valueChangedSlider:(id)sender {
    handleView = [_slider.subviews lastObject];
    label = [[UILabel alloc] initWithFrame:handleView.bounds];
    label = (UILabel*)[handleView viewWithTag:1000];

    if (label==nil) {

        label = [[UILabel alloc] initWithFrame:handleView.bounds];

        label.tag = 1000;

        [label setFont:[UIFont systemFontOfSize:12]];
        label.textColor = [UIColor redColor];
        label.backgroundColor = [UIColor clearColor];

        label.textAlignment = NSTextAlignmentCenter;

        [handleView addSubview:label];


    }
    label.text = [NSString stringWithFormat:@"%0.2f", self.slider.value];
}

Well, I subclassed the UISlider and override the methods of NSControl.好吧,我继承了 UISlider 并覆盖了 NSControl 的方法。 You just need to change your class into storyboard你只需要把你的班级改成故事板

I label can be add above thumb as per requirement.可以根据需要在拇指上方添加 I 标签。

class CustomSlider: UISlider {


let label = UILabel()

override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
    let track = super.beginTracking(touch, with: event)
    label.text = "\(Int(self.value))"
    label.frame = CGRect.init(x: self.thumbCenterX, y: -10, width: 20, height: 20)
    self.addSubview(label)
    return track
}


override func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
    let track = super.continueTracking(touch, with: event)
    label.frame = CGRect.init(x: self.thumbCenterX - 5 , y: 6, width: 30, height: 20)
    label.text = "\(Int(self.value))"
    return track
}

override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
    super.endTracking(touch, with: event)
    label.removeFromSuperview()
}}



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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM