最近有个需求, App 内需要一个 RGB 的 拾色器. 网上也没有找到好的轮子, 只好自己造一个了.
轮子的大概效果是这样子的:

UISlider 动态渐变背景
UISlider 类本身仅仅为开发者提供了 4 个属性来设置其背景样式:
1
2
3
4
5
6
7
8
// 滑块左面背景图片
@property(nullable, nonatomic,strong) UIImage *minimumValueImage;
// 滑块右面背景图片
@property(nullable, nonatomic,strong) UIImage *maximumValueImage;
// 滑块左面背景颜色
@property(nullable, nonatomic,strong) UIColor *minimumTrackTintColor;
// 滑块右面背景颜色
@property(nullable, nonatomic,strong) UIColor *maximumTrackTintColor;
以及若干方法, 但是效果跟上面 4 个属性效果差不多.
实现动态的渐变背景只能通过 自定义 来完成了.
系统有专门为做渐变而封装的 CAGradientLayer 类.
此处就用 CAGradientLayer 来做 UISlider 的渐变背景.
我们的自定义视图层级如下结构所示:
1
2
3
UIView (父视图)
 |- CAGradientLayer (渐变背景)
 |- UISlider (滑动视图)
创建一个 ZHKColorSlider 类, 为我们的动态渐变背景的 Slider 类.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
typedef void(^ColorSliderChangedBlock)(CGFloat value);
@interface ZHKColorSlider : UIView
// 当前 Slider 的值
@property (nonatomic, assign) CGFloat value;    
// Slider 值改变时候的回调
@property (nonatomic, copy) ColorSliderChangedBlock changedBlock;  
// 滑动视图
@property (nonatomic, strong) UISlider *slider;
// 背景渐变图层
@property (nonatomic, strong) CAGradientLayer *backLayer;
/**
 设置背景由左向右的渐变颜色
 @param startColor 开始颜色 (左侧)
 @param endColor   结束颜色 (右侧)
 */
- (void)startColor:(UIColor *)startColor endColor:(UIColor *)endColor;
@end
注意点
- 设置 
UISlider的minimumTrackTintColor和maximumTrackTintColor为clearColor. 防止影响我们自定义的渐变背景效果. - UISlider 的设置:
    
1 2 3 4
// 这样设置方便颜色的取值 // 不一定非要这个设置, 只是为了方便取值和转换. _slider.minimumValue = 0.0f; _slider.maximumValue = 255.0f;
 backLayer背景渐变图层的设置:1 2 3 4
// 设置渐变的方向为从 左 向 右 _backLayer.startPoint = CGPointMake(0, 0); _backLayer.endPoint = CGPointMake(1, 0); _backLayer.locations = @[@0.0, @1.0];
不贴过多的代码, 只写一下 原理 和 注意点. 下面会放 demo 地址.
调色器
调色器 为 3 个背景可以动态渐变的 Slider 组成. 且 3 个 Slider 之间有联动效果. 最终结合 3 个 Slider 的值生成我们的结果即可达成我们的目的.
创建 ZHKSliderColorPicker 类, 作为 滑动视图 和 联动效果 的封装.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@class ZHKSliderColorPicker;
@protocol ColorSliderPickerDelegate <NSObject>
- (void)picker:(ZHKSliderColorPicker *)picker color:(UIColor *)color;
@end
@interface ZHKSliderColorPicker : UIView
// 当前拾色器的颜色
@property (nonatomic, strong) UIColor *color;
// R 滑动视图
@property (nonatomic, strong) ZHKColorSlider *RSlider;
// G 滑动视图
@property (nonatomic, strong) ZHKColorSlider *GSlider;
// B 滑动视图
@property (nonatomic, strong) ZHKColorSlider *BSlider;
// 即时回调代理
@property (nonatomic, weak) id <ColorSliderPickerDelegate> delegate;
@end
属性 color 的 Setter 用于设置调色器 当前颜色 和 滑动视图的联动分布. Getter 用于获取当前的 调色结果.
滑动视图的联动
RSlider, GSlider, BSlider 任意一个值得变化, 都会造成另外 2 个 Slider 背景颜色的变化.
因此此处在 Slider 的值发生改变的时候, 需要在其回调方法内调用其他 2 个 Slider 的方法:
1
- (void)startColor:(UIColor *)startColor endColor:(UIColor *)endColor
回调方法的联动逻辑以 RSlider 的回调为例:
1
2
3
4
- (void)redAction:(CGFloat)value {
    [_GSlider startColor:COLOR(_RSlider.value, 0, _BSlider.value, 1) endColor:COLOR(_RSlider.value, 255, _BSlider.value, 1)];
    [_BSlider startColor:COLOR(_RSlider.value, _GSlider.value, 0, 1) endColor:COLOR(_RSlider.value, _GSlider.value, 255, 1)];
}
GSlider 和 BSlider 的回调方法与 RSlider 逻辑相同, 举一反三即可.
其中 COLOR 宏如下:
1
2
// 通过 RGB 创建颜色对象
#define COLOR(R, G, B, A) [UIColor colorWithRed:R / 255.0 green:G / 255.0 blue:B / 255.0 alpha:A]
如果需要即时获取当前调色器的颜色结果, 在联动方法的末尾 回调代理 即可.
注意点:
Slider的value范围是0 ~ 255, 因此在数据处理的时候需要注意.- 由外部给 
color属性赋值的时候, 不仅要改变Slider的value, 还要改变其渐变背景, 使其视觉效果和数值在逻辑上达到统一.