Mac开发之重写NSSlider(比酷狗的播放进度条好看)

Mac开发如果觉得系统自带Slider不好看,可以通过重绘让自己软件的Slider变得好看一点。与iOS开发不同的是,Mac开发控件重绘没有那么直接,但也不算复杂。下面说一下怎么通过继承NSSlider和NSSliderCell重绘NSSlider。


新建一个Project,名字为:CustomSlider。打开Main.storyboard,从IB中拉几个slider,如图一所示:


图一

新建几个类,分别是CustomSlider、CustomSliderCell和NSColor+Hexa,下面是这几个类的详细内容:

CustomSlider.h

//
//  CustomSlider.h
//  X300A
//
//  Created by Chen Ling on 15/3/2018.
//  Copyright © 2018 Chen Ling. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface CustomSlider : NSSlider


@end

CustomSlider.m

//
//  CustomSlider.m
//  CustomSlider
//
//  Created by Chen Ling on 15/3/2018.
//  Copyright © 2018 Chen Ling. All rights reserved.
//

#import "CustomSlider.h"

@interface CustomSlider()

@property (nonatomic, strong) NSTrackingArea *trackingArea;

@end

@implementation CustomSlider

- (instancetype)initWithCoder:(NSCoder *)coder {
    if (self = [super initWithCoder:coder]) {
        // init code here
    }
    return self;
}


#pragma mark - 设置mouse追踪区域
-(void)updateTrackingAreas
{
    [super updateTrackingAreas];
    if(_trackingArea != nil) {
        [self removeTrackingArea:_trackingArea];
        
    }
    
    int opts = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways);
    
    // 将设置追踪区域为控件大小
    // 设置鼠标追踪区域,如果不设置追踪区域,mouseEntered和mouseExited会无效
    _trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds]
                                                  options:opts
                                                    owner:self
                                                 userInfo:nil];
    [self addTrackingArea:_trackingArea];
}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    
    // Drawing code here.
}

#pragma mark - 点击knob效果, 屏蔽就没有点下去的效果
- (BOOL)needsPanelToBecomeKey{
    [super needsPanelToBecomeKey];
    return YES;
}

//- (BOOL)becomeFirstResponder{
//    [super becomeFirstResponder];
//    return YES;
//}

#pragma mark - mouse action
- (void)mouseEntered:(NSEvent *)theEvent
{
    [super mouseEntered:theEvent];
    NSLog(@"mouseEntered");
    self.highlighted = YES;
}

- (void)mouseExited:(NSEvent *)theEvent
{
    [super mouseExited:theEvent];
    NSLog(@"mouseExited");
    self.highlighted = NO;
}


@end
CustomSliderCell.h
//
//  CustomSliderCell.h
//  CustomSlider
//
//  Created by Chen Ling on 15/3/2018.
//  Copyright © 2018 Chen Ling. All rights reserved.

#import <Cocoa/Cocoa.h>


#define ColorWithRGB(colorCode)     [NSColor colorWithDeviceRed:((colorCode>>16)&0xFF)/255.0 green:((colorCode>>8)&0xFF)/255.0 blue:((colorCode)&0xFF)/255.0 alpha:1.0];

#define SLIDER_PROGRESS_DEFAUT_COLOR       ColorWithRGB(0x3399FF)
#define SLIDER_BACKGROUND_DEFAUT_COLOR     ColorWithRGB(0x969696)
#define SLIDER_KNOB_DEFAUT_COLOR           ColorWithRGB(0x3399FF)
#define SLIDER_DEFAUT_HEIGHT               3.0
#define SLIDER_DEFAUT_BAR_RADIUS           5.0
#define SLIDER_DEFAUT_KNOB_WIDTH           8.0
#define SLIDER_DEFAUT_KNOB_HEIGHT          8.0


IB_DESIGNABLE
@interface CustomSliderCell : NSSliderCell

@property (nonatomic, strong) IBInspectable NSColor *sliderProgressColor;
@property (nonatomic, strong) IBInspectable NSColor *sliderBackgroundColor;
@property (nonatomic, strong) IBInspectable NSColor *sliderKnobColor;
@property (nonatomic, assign) IBInspectable CGFloat sliderHeight;
@property (nonatomic, assign) IBInspectable CGFloat sliderBarRadius;
@property (nonatomic, assign) IBInspectable CGFloat sliderKnobWidth;
@property (nonatomic, assign) IBInspectable CGFloat sliderKnobHeight;
@end

CustomSliderCell.m

//
//  CustomSliderCell.m
//  CustomSlider
//
//  Created by Chen Ling on 15/3/2018.
//  Copyright © 2018 Chen Ling. All rights reserved.
//

#import "CustomSliderCell.h"
#import "NSColor+Hexa.h"
#import "CustomSlider.h"

@interface CustomSliderCell()

// save leftBar's frame, and use to caculate Knob's frame
@property (assign) NSRect leftBarRect;

@end

@implementation CustomSliderCell


-(instancetype)initWithCoder:(NSCoder *)coder {
    if (self = [super initWithCoder:coder]) {
        self.sliderProgressColor = SLIDER_PROGRESS_DEFAUT_COLOR;
        self.sliderBackgroundColor = SLIDER_BACKGROUND_DEFAUT_COLOR;
        self.sliderKnobColor = SLIDER_KNOB_DEFAUT_COLOR;
        self.sliderHeight = SLIDER_DEFAUT_HEIGHT;
        self.sliderBarRadius = SLIDER_DEFAUT_BAR_RADIUS;
        self.sliderKnobWidth = SLIDER_DEFAUT_KNOB_WIDTH;
        self.sliderKnobHeight = SLIDER_DEFAUT_KNOB_HEIGHT;
    }
    return self;
}

- (void)drawBarInside:(NSRect)rect flipped:(BOOL)flipped {
    rect.size.height = self.sliderHeight;
    // Bar radius
    CGFloat barRadius = self.sliderBarRadius;
    // Knob position depending on control min/max value and current control value.
    CGFloat value = ([self doubleValue]  - [self minValue]) / ([self maxValue] - [self minValue]);
    // Final Left Part Width
    CGFloat finalWidth = value * ([[self controlView] frame].size.width - self.sliderKnobWidth);
    
    // Left Part Rect
    NSRect leftRect = rect;
    leftRect.size.width = finalWidth;
    self.leftBarRect = leftRect;
    
    // Draw Left Part
    NSBezierPath* bg = [NSBezierPath bezierPathWithRoundedRect: rect xRadius: barRadius yRadius: barRadius];
    [self.sliderBackgroundColor setFill];
    [bg fill];
    
    // Draw Right Part
    NSBezierPath* active = [NSBezierPath bezierPathWithRoundedRect: leftRect xRadius: barRadius yRadius: barRadius];
    [self.sliderProgressColor setFill];
    [active fill];
    
}

- (void)drawKnob:(NSRect)knobRect {
    
    if (((CustomSlider *)self.controlView).highlighted) {
        NSRect customKnobRect = NSMakeRect(_leftBarRect.size.width, _leftBarRect.origin.y + _leftBarRect.size.height / 2 - self.sliderKnobHeight / 2, self.sliderKnobWidth, self.sliderKnobHeight);
    
        // Draw Left Part
        NSBezierPath* bg = [NSBezierPath bezierPathWithRoundedRect: customKnobRect xRadius: self.sliderKnobWidth / 2 yRadius: self.sliderKnobHeight / 2];
        [self.sliderKnobColor  setFill];
        [bg fill];
    }

}


@end

NSColor+Hexa.h

//
//  NSColor+Hexa.h
//  CustomSlider
//
//  Created by Chen Ling on 15/3/2018.
//  Copyright © 2018 Chen Ling. All rights reserved.
//
//

#import <Cocoa/Cocoa.h>

@interface NSColor (Hexa)

+ (NSColor *)colorFromHexadecimalValue:(NSString *)hexaString;

@end
NSColor+Hexa.m
//
//  NSColor+Hexa.m
//  CustomSlider
//
//  Created by Chen Ling on 15/3/2018.
//  Copyright © 2018 Chen Ling. All rights reserved.
//
//

#import "NSColor+Hexa.h"

@implementation NSColor (Hexa)


+ (NSColor *)colorFromHexadecimalValue:(NSString *)hexaString {
    
    if ([hexaString hasPrefix:@"#"]) {
        hexaString = [hexaString substringWithRange:NSMakeRange(1, [hexaString length] - 1)];
    }
    
    unsigned int colorCode = 0;
    
    if (hexaString) {
        NSScanner *scanner = [NSScanner scannerWithString:hexaString];
        (void)[scanner scanHexInt:&colorCode];
    }
    
    return [NSColor colorWithDeviceRed:((colorCode>>16)&0xFF)/255.0 green:((colorCode>>8)&0xFF)/255.0 blue:((colorCode)&0xFF)/255.0 alpha:1.0];
}
@end

将前面那三个NSSlider的类分别设置为CustomSlider,将它们的NSSliderCell的类设置为CustomSliderCell,在NSSliderCell的Attributes Inspector中分别设置为如图二图三图四所示:

        

图二


图三


图四

运行效果:


github地址:https://github.com/Mozartisnotmyname/CustomSlider


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值