首页 UISlider 实现调色器 (渐变背景)
文章
取消

UISlider 实现调色器 (渐变背景)

最近有个需求, 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

注意点

  1. 设置 UISliderminimumTrackTintColormaximumTrackTintColorclearColor. 防止影响我们自定义的渐变背景效果.
  2. UISlider 的设置:
    1
    2
    3
    4
    
    // 这样设置方便颜色的取值
    // 不一定非要这个设置, 只是为了方便取值和转换.
    _slider.minimumValue = 0.0f;
    _slider.maximumValue = 255.0f;
    
  3. 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

属性 colorSetter 用于设置调色器 当前颜色滑动视图的联动分布. Getter 用于获取当前的 调色结果.

滑动视图的联动

RSlider, GSlider, BSlider 任意一个值得变化, 都会造成另外 2Slider 背景颜色的变化. 因此此处在 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)];
}

GSliderBSlider 的回调方法与 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]

如果需要即时获取当前调色器的颜色结果, 在联动方法的末尾 回调代理 即可.

注意点:

  1. Slidervalue 范围是 0 ~ 255, 因此在数据处理的时候需要注意.
  2. 由外部给 color 属性赋值的时候, 不仅要改变 Slidervalue, 还要改变其 渐变背景, 使其视觉效果和数值在逻辑上达到统一.

Demo 地址

地址: https://github.com/ZHK1024/ZHKColorPicker

本文由作者按照 CC BY 4.0 进行授权

iOS App 被判定为太简被拒绝上架

iOS 超简单的 旋转/翻转/放大 UIImage 的方法