UISlider自定义(自带value与旋转支持)

首先申明,代码是参考https://github.com/QiShare/QiSlider 改造而成

Github中这个代码其实在IOS 14上是有问题的,即使ISSUE下面几位高手的解释也不是很适用。经过我的实践,再加上我这边旋转的需求,改造如下:
头文件:

@interface SWSlider : UISlider

@property (nonatomic, strong) UIFont *textFont;
@property (nonatomic, strong) UIColor *textColor;
@property (nonatomic, copy) void(^valueChanged)(UISlider *);
@property (nonatomic, assign) CGFloat angle;

@end

这里的angle就是用来调整旋转后的效果的,因为一般来说,slider整体旋转后,最大值最小值以及当前值的标识应该保持水平。 angle的设置代码如下:

-(void)setAngle:(CGFloat)angle{
    _angle = angle;
    [self setTransform:CGAffineTransformMakeRotation(angle)];
}

然后slider设置angle来旋转,不用设置transform。

接下是对QISider的修改:
1)获取thumbView部分:

- (UIView *)thumbView {
    if(@available(iOS 14.0, *)) {
      if (!_thumbView) {
          UIView *view = self.subviews[0];
          if (view.subviews.count > 2) {
              _thumbView = view.subviews[view.subviews.count - 1];
              if([view.subviews[0] isKindOfClass:[UIImageView class]]) {
                  view.subviews[0].transform = CGAffineTransformMakeRotation(-self.angle);
              }
              if([view.subviews[1] isKindOfClass:[UIImageView class]]) {
                  view.subviews[1].transform = CGAffineTransformMakeRotation(-self.angle);
              }
          }
      }
    }else {
      if (!_thumbView && self.subviews.count > 2) {
          _thumbView = self.subviews[2];
      }
    }
    return _thumbView;
}

根据个人调试,当有设置maximumValueImage与minimumValueImage,subviews[2]并不是thumview,它一直是在数组最后一位,而最开始两位是maximumValueImage与minimumValueImage。

2)setValue的改造

- (void)setTextValue:(NSString *)textValue {
    if(![_textValue isEqualToString:textValue]) {
        _textValue = textValue;
        
        self.valueLabel.text = textValue;
        [self.valueLabel sizeToFit];
        
        CGFloat delay = self.thumbView?0:200;
        __weak typeof(self) weakSelf = self;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
            CGFloat width = weakSelf.valueLabel.bounds.size.width;
            weakSelf.valueLabel.center = CGPointMake(weakSelf.thumbView.bounds.size.width / 2, -weakSelf.valueLabel.bounds.size.height / 2 - width / 3);
            if (!weakSelf.valueLabel.superview) {
                [weakSelf.thumbView addSubview:weakSelf.valueLabel];
            }
        });
    }
}

调试发现最开始设置初始值的时候,subview中是空的,所以需要加一个延时,否则无法显示初始值。

3)然后是label添加对旋转的支持(旋转还原):

- (UILabel *)valueLabel {
    if (!_valueLabel) {
        _valueLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        _valueLabel.textColor = _textColor?:self.thumbTintColor;
        _valueLabel.font = _textFont?:[UIFont systemFontOfSize:14.0];
        _valueLabel.textAlignment = NSTextAlignmentCenter;
        _valueLabel.transform = CGAffineTransformMakeRotation(-self.angle);
    }
    return _valueLabel;
}

4)使用例子:

CGFloat sliderW = CSSCREEN_HEIGHT / 3.0f;
    CGFloat sliderH = 50.0f;
    self.slider = [[SWSlider alloc]initWithFrame:CGRectMake((CSSCREEN_WIDTH - sliderW / 2) - 40, (CSSCREEN_HEIGHT - sliderH) * 0.5f - 40, sliderW, sliderH)];
    self.slider.maximumValue = 20;
    self.slider.minimumValue = 2;
    self.slider.continuous = YES;
    self.slider.maximumTrackTintColor = [UIColor whiteColor];
    self.slider.textColor = [UIColor whiteColor];
    self.slider.textFont = [UIFont systemFontOfSize:25.0];
    self.slider.maximumValueImage = [self imageByString:@"20.0X"];
    self.slider.minimumValueImage = [self imageByString:@"1.0X"];
    self.slider.angle = -M_PI_2;
    
    [self.view addSubview:self.slider];
    [self.slider addTarget:self action:@selector(sliderValueDidChanged:) forControlEvents:UIControlEventValueChanged];
    self.slider.value = 3.4f;

至于文字转图片代码可参考如下:

- (UIImage*)imageByString:(NSString*)string{
    return [UIImage createImageBYString:string font:[UIFont systemFontOfSize:15.0] bgColor:[UIColor colorWithRed:122 green:122 blue:122 alpha:0] textColor:[UIColor whiteColor] textAlignment:NSTextAlignmentCenter];
}

UIImage的扩展:

+(UIImage *)createImageBYString:(NSString*)string font:(UIFont *)font bgColor:(UIColor*)bgColor textColor:(UIColor*)textColor textAlignment:(NSTextAlignment)textAlignment {
    NSDictionary *attributeDic = @{NSFontAttributeName:font};
    CGSize sizeStr = [string boundingRectWithSize:CGSizeMake(1000, 1000) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine attributes:attributeDic context:nil].size;
    CGFloat maxSize = (sizeStr.width > sizeStr.height)?sizeStr.width:sizeStr.height;
    CGSize size = CGSizeMake(maxSize, maxSize);
    
    if ([UIScreen.mainScreen respondsToSelector:@selector(scale)]) {
        if (UIScreen.mainScreen.scale == 2.0) {
            UIGraphicsBeginImageContextWithOptions(size, NO, 1.0);
        } else {
            UIGraphicsBeginImageContext(size);
        }
    } else {
        UIGraphicsBeginImageContext(size);
    }
       
    CGContextRef context = UIGraphicsGetCurrentContext();
    //[[UIColor colorWithRed:122 green:122 blue:122 alpha:0.05] set];
    [bgColor set];
    CGRect rect = CGRectMake(0, 0, size.width + 1, size.height + 1);
    CGContextFillRect(context, rect);
    
    NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
    paragraph.alignment = textAlignment;
       
    NSDictionary *attributes = @{
        NSForegroundColorAttributeName:textColor,
        NSFontAttributeName:font,
        NSParagraphStyleAttributeName:paragraph
    };
    
    rect = CGRectMake(0, (size.height - sizeStr.height)/2, sizeStr.width + 1, sizeStr.height + 1);
    [string drawInRect:rect withAttributes:attributes];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
       
    return image;
}

版权声明:本文为dingpwen原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。