【问题标题】:Is that possible to add a label to the UISlider's thumb image?是否可以向 UISlider 拇指图像添加标签?
【发布时间】:2011-05-18 15:56:07
【问题描述】:

我想为滑块的拇指添加一个标签,该标签应该显示滑块的值,并且当拇指被拖向右侧时也会发生变化。 可以吗??

任何 cmets 或建议将不胜感激。

【问题讨论】:

    标签: ios objective-c iphone uislider


    【解决方案1】:

    我从滑块 (UIImageView) 中抓取拇指图像并将我的标签添加到其中。干净整洁。

    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;
    

    然后,您可以随时更改 label.text。

    注意:UISlider 的子视图顺序可能会在未来发生变化,但拇指不太可能不再是最顶层视图,因为它始终是滑块中的主要交互点。

    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 = "!!"
            }
        }
    }
    

    【讨论】:

    • 如何快速做到这一点?
    • 两个问题。 1.你把这段代码ViewDidLoad放在哪里还是在sliderLabel函数中? 2. 什么是 SliderLabel?
    • @bradfordgray 您必须引用您的滑块:“slider”,以及您自己的属性,稍后您将使用该属性来引用您正在创建并添加到滑块的标签:“sliderLabel”。您可以在 viewDidLoad 中执行此操作,但这两个属性都应在 viewController(或您所在的任何文件)的顶部定义。
    • 所以为了清楚起见@IBOutlet 弱变量滑块:UISlider!,并使sliderLabel 成为双精度。但是如果你这样做,你就不能按这个顺序给一个标签分配一个双精度。我对你是如何做到这一点感到有些困惑。感谢您的帮助。
    • 最后我不是很明白,但是当我做断点时,slider.subview.last 为? UIImageView 从来都不是真的。
    【解决方案2】:

    您可以执行与此示例类似的操作,将文本直接绘制到您的拇指图像上。这是一个粗略的示例,因此您需要对其进行更改以使其对您的项目有意义。

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

    【讨论】:

    • 它给了我一个错误提示,请求成员 thumbImage 不是结构或联合。
    • 我修复了错误,但它仍然显示滑块下方的文本并且也未对齐。能否再给点提示
    • 更改 CGContextShowTextAtPoint() 函数以调整文本的绘制位置。
    • 我得到它来改变你必须使用的文本颜色 CGContextSetRGBFillColor(context,255,255,255, 1);
    • 我认为这种设计可能是更好的选择。 cocoacontrols.com/platforms/ios/controls/elcslider
    【解决方案3】:

    Swift 3.2 中自定义类的简单实现。这对我来说效果很好。

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

    希望对你有帮助:)

    【讨论】:

    • 太棒了!效果很好
    • 你是冠军兄弟 :)
    【解决方案4】:

    在 Interface Builder 中添加 UISliderUILabel。创建 IBOutlets 以在代码中访问它们并添加 IBAction 以响应滑块值的变化。

    然后在你的代码中写:

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

    编辑: 要使用代码创建滑块和标签,请添加:

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

    【讨论】:

    • 这种方法的唯一问题是标签在用户完成移动滑块之前不会移动。
    • Deepak,我相信如果滑块的连续属性设置为 YES,它会随着值的更改而更新,而不仅仅是在更改完成时更新。
    • 使用 IB 添加滑块时,默认情况下连续设置为 YES
    • 如果我直接通过代码而不是通过 IB 来做这有什么区别吗?如果您提供一些带有代码而不是 IB 的解决方案,我将不胜感激,因为如果将滑块更改为从 IB 工作,那将是一团糟。
    • 当我在做 self._statSlider 时,它给我的错误信息是无法设置对象 - 只读属性或找不到设置器。
    【解决方案5】:

    您可以使用-thumbRectForBounds:trackRect:value:] 访问滑块的缩略图视图的矩形,因此如果您添加一个UILabel 子视图,您可以使用此返回的矩形将其与-layoutSubviews 中的缩略图视图对齐。

    但是,如果您想使用 Autolayout 将标签与拇指图像对齐,则需要直接访问拇指的 UIImageView。我一般不热衷于探索 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;
    }
    

    API 提供了为拇指设置UIImage 的功能,因此您可以将其用作测试以确保您没有获得其他图像视图。如果您自己明确设置缩略图图像,这会更加安全(因为将来可能更改滑块以绘制缩略图图像并不是不可能...)。此外,拇指图像视图当前是最后一个子视图(不能保证继续前进),所以我在这里进行反向枚举,希望尽可能快地得到它,同时不对它的索引做出假设。

    注意:我不得不懒惰地创建我的拇指标签,因为UISlider 的子视图似乎如此。

    【讨论】:

    • @SandeepAggarwal 哪个 SDK?
    • 对不起!在添加 Slider 之前我正在使用此代码,现在当我在 layoutSubviews 中调用此代码 sn-p 时工作。谢谢!!
    • 好的,这是个好消息。这在非主要版本上中断会很奇怪。 UIKit 往往比较“懒惰”,所以听到这个并不奇怪
    【解决方案6】:

    让这变得又好又简单..首先这是最终结果

    现在,代码:

    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;
    

    以上方法来自我使用的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;
    }
    

    【讨论】:

    • 你有这个样品吗?
    【解决方案7】:
    - (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];
    }
    

    【讨论】:

      【解决方案8】:

      好吧,我继承了 UISlider 并覆盖了 NSControl 的方法。您只需要将您的课程更改为故事板

      可以根据需要在拇指上方添加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
      }}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多