今天分享一个自定义的silider,因为系统自带的使用起来有诸多不便,主要的一个原因就是系统自带的未选中区域是透明的,也许小伙伴们有别的思路或者别的解决方案,我这里直接就基于NSView
自定义了一个,代码也比较简单,也有注释,我就不多讲解了,直接上代码

SHSlider.h
#import <Cocoa/Cocoa.h>
typedef void(^ChangeValueBlock)(float value);
NS_ASSUME_NONNULL_BEGIN
@interface SHSlider : NSView
@property (nonatomic , strong , nonnull) NSColor *selectColor;//选中区域颜色
@property (nonatomic , strong , nonnull) NSColor *unSelectColor;//未选中区域颜色
@property (nonatomic , strong , nonnull) NSColor *cachColor;//缓冲区域颜色
@property (nonatomic , strong , nonnull) NSColor *valueColor;//圆圈颜色
@property (nonatomic , assign) float value;//值,默认:0
@property (nonatomic , assign) float cacheValue;//缓冲值
@property (nonatomic , assign) float maxValue;//缓冲值,默认:100
@property (nonatomic , copy) ChangeValueBlock changeValueBlock;
@end
NS_ASSUME_NONNULL_END
SHSlider.m
#import "SHSlider.h"
@interface SHSlider ()
@property (nonatomic , strong) NSView *selectView;//选中视图
@property (nonatomic , strong) NSView *unSelectView;//未选中视图
@property (nonatomic , strong) NSView *cacheView;//缓冲
@property (nonatomic , strong) NSImageView *valueView;//圆球
@property (nonatomic , strong) NSTrackingArea *trackingArea;//监听鼠标
@property (nonatomic , assign) BOOL isDragged;//正在拖动
@property (nonatomic , assign) float minValue;//缓冲值,默认:0
@end
@implementation SHSlider
- (BOOL)isFlipped{return YES;}
- (BOOL)mouseDownCanMoveWindow{return NO;}
- (instancetype)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.wantsLayer = YES;
self.layer.masksToBounds = NO;
self.value = 0;
self.cacheValue = 0;
self.minValue = 0;
self.maxValue = 100;
}
return self;
}
- (void)layout
{
if (self.frame.size.width == 0) return;
CGFloat padding = 2;
if (self.isDragged == NO) {
CGFloat location = self.value*(self.bounds.size.width-11)/self.maxValue;
self.unSelectView.frame = NSMakeRect(0, padding, self.bounds.size.width, self.bounds.size.height-padding);
self.selectView.frame = NSMakeRect(0, padding, location, self.bounds.size.height-padding);
self.valueView.frame = NSMakeRect(location < 5 ? 0 : location - 5, self.bounds.size.height*0.5-5, 11, 11);
}
if (_cacheView && self.cacheValue <= self.maxValue) {
CGFloat cache = self.cacheValue*self.bounds.size.width/self.maxValue;
self.cacheView.frame = NSMakeRect(0, padding, cache, self.bounds.size.height - padding);
}
}
#pragma mark - 监听鼠标
- (void)updateTrackingAreas
{
if (self.trackingAreas.count > 0) {
[self removeTrackingArea:_trackingArea];
}
_trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:(NSTrackingEnabledDuringMouseDrag|NSTrackingActiveInActiveApp|NSTrackingInVisibleRect|NSTrackingAssumeInside|NSTrackingCursorUpdate)owner:self userInfo:nil];
[self addTrackingArea:_trackingArea];
}
- (void)mouseDown:(NSEvent *)event
{
NSPoint point = NSMakePoint(event.locationInWindow.x-self.frame.origin.x, 0);
if (NSPointInRect(point, self.valueView.frame)) {
self.isDragged = YES;
}
}
- (void)mouseUp:(NSEvent *)event
{
self.isDragged = NO;
}
- (void)mouseDragged:(NSEvent *)event
{
if (self.isDragged == YES) {
self.value = (event.locationInWindow.x-self.frame.origin.x)/(self.bounds.size.width-6)*self.maxValue;
CGFloat padding = 2;
CGFloat location = self.value*(self.bounds.size.width-6)/self.maxValue;
self.selectView.frame = NSMakeRect(0, padding, location, self.bounds.size.height-padding);
self.valueView.frame = NSMakeRect(location < 5 ? 0 : location-5, self.bounds.size.height*0.5-5, 11, 11);
!self.changeValueBlock ? : self.changeValueBlock(self.value);
}
}
#pragma mark - 赋值
- (void)setValue:(float)value
{
if (value <= self.maxValue && value >= self.minValue) {
_value = value;
if (self.maxValue - value <= 0.01) {
_value = self.maxValue;
}else if(value <= 0.01){
_value = self.minValue;
}
[self layout];
}
}
- (void)setCacheValue:(float)cacheValue
{
if (cacheValue <= self.maxValue && self.bounds.size.height > 0 ) {
_cacheValue = cacheValue;
if (!_cacheView) {
[self addSubview:self.cacheView positioned:NSWindowBelow relativeTo:self.selectView];
}
[self layout];
}
}
- (void)setCachColor:(NSColor *)cachColor
{
_cachColor = cachColor;
self.cacheView.layer.backgroundColor = cachColor.CGColor;
}
- (void)setValueColor:(NSColor *)valueColor
{
_valueColor = valueColor;
self.valueView.layer.backgroundColor = valueColor.CGColor;
}
- (void)setSelectColor:(NSColor *)selectColor
{
_selectColor = selectColor;
_selectView.layer.backgroundColor = selectColor.CGColor;
}
- (void)setUnSelectColor:(NSColor *)unSelectColor
{
_unSelectColor = unSelectColor;
self.unSelectView.layer.backgroundColor = unSelectColor.CGColor;
}
#pragma mark - lazy -
- (NSView *)selectView//选中视图
{
if (!_selectView) {
_selectView = [[NSView alloc] init];
_selectView.wantsLayer = YES;
_selectView.layer.backgroundColor = NSColor.whiteColor.CGColor;
[self addSubview:_selectView];
[self addSubview:self.valueView positioned:NSWindowAbove relativeTo: _selectView];
}
return _selectView;
}
- (NSView *)unSelectView//未选中视图
{
if (!_unSelectView) {
_unSelectView = [[NSView alloc] init];
_unSelectView.wantsLayer = YES;
_unSelectView.layer.backgroundColor = NSColor.grayColor.CGColor;
[self addSubview:_unSelectView];
}
return _unSelectView;
}
- (NSView *)cacheView//选中视图
{
if (!_cacheView) {
_cacheView = [[NSView alloc] init];
_cacheView.wantsLayer = YES;
_cacheView.layer.backgroundColor = NSColor.lightGrayColor.CGColor;
}
return _cacheView;
}
- (NSImageView *)valueView//选中视图
{
if (!_valueView) {
_valueView = [NSImageView imageViewWithImage:[NSImage imageNamed:NSImageNameTouchBarRecordStartTemplate]];
_valueView.imageScaling = NSImageScaleAxesIndependently;
_valueView.contentTintColor = NSColor.whiteColor;
[self addSubview:_valueView];
}
return _valueView;
}
@end
- 可以用鼠标拖动更改进度
- 有缓存进度(使用是赋值就可以,不赋值不添加控件)
- 内部使用的frame,但是外部也可以使用约束
有需要的小伙伴可以直接复制粘贴使用
完工
网友评论