ForgetSou | Blog

❤ 武统台湾 刻不容缓 ❤

0%

macOS开发-NSButton

一.简介

按钮,主要用户通过NSControl控制点击、高亮等事件,同iOSUIButton

@interface NSButton : NSControl <NSUserInterfaceValidations, NSAccessibilityButton, NSUserInterfaceCompression>
/**
* NSButton 定义于 AppKit 框架;
* NSButton 继承 NSControl
*/

二.源码

1.创建NSButton

// 创建带有标题和图像的标准按钮。在从左到右的本地化中,图像显示在标题的左侧。在从右到左的本地化中,它显示在右侧。
+ (instancetype)buttonWithTitle:(NSString *)title image:(NSImage *)image target:(nullable id)target action:(nullable SEL)action API_AVAILABLE(macos(10.12));
// 创建带有标题的标准按钮。
+ (instancetype)buttonWithTitle:(NSString *)title target:(nullable id)target action:(nullable SEL)action API_AVAILABLE(macos(10.12));
// 使用提供的图像创建标准按钮。设置图像的accessibilityDescription属性以确保此控件的可访问性。
+ (instancetype)buttonWithImage:(NSImage *)image target:(nullable id)target action:(nullable SEL)action API_AVAILABLE(macos(10.12));
// 使用提供的标题创建标准复选框。
+ (instancetype)checkboxWithTitle:(NSString *)title target:(nullable id)target action:(nullable SEL)action API_AVAILABLE(macos(10.12));
// 使用提供的标题创建标准单选按钮。s
+ (instancetype)radioButtonWithTitle:(NSsString *)title target:(nullable id)target action:(nullable SEL)action API_AVAILABLE(macos(10.12));

2.按钮基础配置

typedef NS_ENUM(NSUInteger, NSButtonType) {
NSButtonTypeMomentaryLight = 0,
NSButtonTypePushOnPushOff = 1,
NSButtonTypeToggle = 2,
NSButtonTypeSwitch = 3,// 勾选框,不支持带图片,适合做多选
NSButtonTypeRadio = 4,// 勾选框,不支持带图片,适合做单选。
NSButtonTypeMomentaryChange = 5,// 文字会闪烁
NSButtonTypeOnOff = 6,
NSButtonTypeMomentaryPushIn = 7,
NSButtonTypeAccelerator API_AVAILABLE(macos(10.10.3)) = 8,
NSButtonTypeMultiLevelAccelerator API_AVAILABLE(macos(10.10.3)) = 9,
};
// 设置按钮类型,如上NSButtonType枚举
- (void)setButtonType:(NSButtonType)type;
// 显示文本
@property (copy) NSString *title;
// 富文本
@property (copy) NSAttributedString *attributedTitle;
// 按钮打开状态时的标题,部分类型不显示备用标题
@property (copy) NSString *alternateTitle;
// 富文本按钮打开时的标题
@property (copy) NSAttributedString *attributedAlternateTitle;
// 按钮点击时的播放声音,默认为nil
@property (nullable, strong) NSSound *sound;
// 拖动时发送长按或长时间悬停时的操作。默认为否。
@property (getter=isSpringLoaded) BOOL springLoaded API_AVAILABLE(macos(10.10.3));
// 配置NSMultiLevelAcceleratorButton的最大允许级别,允许的值范围为[1,5]。默认为2。
@property NSInteger maxAcceleratorLevel API_AVAILABLE(macos(10.10.3));
// 为“continuous”为“YES”时发送的重复操作消息设置初始延迟和重复间隔(以秒为单位)。
- (void)setPeriodicDelay:(float)delay interval:(float)interval;
/*! 获取在“continuous”为YES时发送的重复操作消息的初始延迟和重复间隔(以秒为单位)。此方法的两个参数都不能为NULL。*/
- (void)getPeriodicDelay:(float *)delay interval:(float *)interval;

3.配置按钮图片

typedef NS_ENUM(NSUInteger, NSBezelStyle) {
NSBezelStyleRounded = 1,
NSBezelStyleRegularSquare = 2,
NSBezelStyleDisclosure = 5,
NSBezelStyleShadowlessSquare = 6,
NSBezelStyleCircular = 7,
NSBezelStyleTexturedSquare = 8,
NSBezelStyleHelpButton = 9,
NSBezelStyleSmallSquare = 10,
NSBezelStyleTexturedRounded = 11,
NSBezelStyleRoundRect = 12,
NSBezelStyleRecessed = 13,
NSBezelStyleRoundedDisclosure = 14,
NSBezelStyleInline API_AVAILABLE(macos(10.7)) = 15,
};
/*! 按钮系统边框样式 */
@property NSBezelStyle bezelStyle;
/*! 是否绘制边框,bordered为NO时,bezelStyle设置无效 */
@property (getter=isBordered) BOOL bordered;
/*! 按钮是否透明 */
@property (getter=isTransparent) BOOL transparent;
/*! 按钮是否仅在指针位于按钮上方时才显示其边框。 */
@property BOOL showsBorderOnlyWhileMouseInside;
/*! 按钮上的图片、设置nil时不显示图片 */
@property (nullable, strong) NSImage *image;
/*! 按钮处于打开状态上的替代图片,部分类型不支持 */
@property (nullable, strong) NSImage *alternateImage;

typedef NS_ENUM(NSUInteger, NSCellImagePosition) {
NSNoImage = 0,// 没有图片
NSImageOnly = 1,// 只显示图片
NSImageLeft = 2,// 图片在左
NSImageRight = 3,// 图片在右
NSImageBelow = 4,// 图片在下
NSImageAbove = 5,// 图片在上
NSImageOverlaps = 6,// 图片文字重叠
NSImageLeading API_AVAILABLE(macos(10.12)) = 7,// 前导
NSImageTrailing API_AVAILABLE(macos(10.12)) = 8 // 尾随
};
/*! 图片相对于标题的位置,NSCellImagePosition类型如是上枚举 */
@property NSCellImagePosition imagePosition;

typedef NS_ENUM(NSUInteger, NSImageScaling) {
NSImageScaleProportionallyDown = 0, // 如果图像对于目的地太大,则将其缩小。保持纵横比。
NSImageScaleAxesIndependently, // 缩放每个维度以完全适合目的地。不保留纵横比。
NSImageScaleNone, // 不缩放.
NSImageScaleProportionallyUpOrDown, // 将图像缩放到最大可能的尺寸,同时(1)停留在目标区域内(2)保持纵横比
NSScaleProportionally API_DEPRECATED("Use NSImageScaleProportionallyDown instead", macos(10.0,10.10)) = 0,
NSScaleToFit API_DEPRECATED("Use NSImageScaleAxesIndependently instead", macos(10.0,10.10)),
NSScaleNone API_DEPRECATED("Use NSImageScaleNone instead", macos(10.0,10.10))
} API_AVAILABLE(macos(10.5));
/*! 缩放 */
@property NSImageScaling imageScaling API_AVAILABLE(macos(10.5));s
/*! 一个布尔值,用于确定按钮的图像和标题在按钮边框中的位置。如果为false,则根据按钮挡板边缘的imagePosition属性定位图像,并且标题位于剩余空间内。如果为true,则基于imagePosition属性将按钮的图像直接定位到标题的旁边,并且图像和标题作为单个单元定位在按钮挡板中。 */
@property BOOL imageHugsTitle API_AVAILABLE(macos(10.12));
/*! 将自定义颜色应用于按钮的边框(在支持它的外观中)。零值表示未修改的按钮外观。默认值为零。 */
@property (nullable, copy) NSColor *bezelColor API_AVAILABLE(macos(10.12.2));
/*! 将淡色应用于模板图像和文本内容,并结合其他适合主题的效果。仅适用于无边界按钮。零值表示没有颜色修改的标准效果集。默认值为零。非模板图像和属性化字符串值不受contentTintColor的影响。 */
@property (nullable, copy) NSColor *contentTintColor API_AVAILABLE(macos(10.14));

4.按钮状态

typedef NSInteger NSControlStateValue NS_TYPED_EXTENSIBLE_ENUM;
static const NSControlStateValue NSControlStateValueMixed = -1;
static const NSControlStateValue NSControlStateValueOff = 0;
static const NSControlStateValue NSControlStateValueOn = 1;
/*! 按钮的状态。按钮支持关闭和打开状态,以及根据“allowsMixedState”属性的值附加的混合状态。 */
@property NSControlStateValue state;
/*! 指示按钮是否允许混合状态的布尔值。如果否,按钮有两种状态(开和关),如果是,按钮有三种状态(开、关和混合)。混合状态通常与复选框和单选按钮一起使用,以指示部分启用的值。 */
@property BOOL allowsMixedState;
/*! 将按钮设置为下一个符合条件的状态。如果按钮允许混合状态,则按以下顺序循环状态:打开、关闭、混合、打开等。如果按钮不允许混合状态,则在关闭和打开之间切换。 */
- (void)setNextState;

/*! 突出显示或取消突出显示按钮。高亮显示使按钮显示为“按下”,这可能包括显示照明挡板,或显示替代图像或标题,具体取决于按钮的类型。*/
- (void)highlight:(BOOL)flag;

5.键盘事件

/*! 此属性包含按钮的键等效项,如果未定义等效项,则包含空字符串。按钮没有默认的等价键。设置与返回字符相等的键将使其充当其窗口的默认按钮。 */
@property (copy) NSString *keyEquivalent;
/*! 一个位掩码,指定应用于按钮的等效键的修改键。掩码位由NSEventModifierFlags选项集定义。按钮键等效修改器掩码中唯一相关的掩码位是NSEventModifierFlagControl、NSEventModifierFlagOption和NSEventModifierFlagCommand。 */
@property NSEventModifierFlags keyEquivalentModifierMask;
/*! 如果事件参数与按钮的等效键匹配,则按钮将短暂高亮显示并执行其操作,然后返回YES。否则,返回NO。 */
- (BOOL)performKeyEquivalent:(NSEvent *)key;

三.macOSiOS 的不同点

1.添加点击事件

iOS:

[button addTarget: action: forControlEvents:];

Mac:

1.需要同时设置 [button setTarget: targetObject:]; [button setAction: @selector(buttonClick:)];

2.初始化的时候添加点击事件

- (void)addButton {
NSButton *button = [NSButton buttonWithTitle:@"使劲戳" target:self action:@selector(buttonClick:)];
button.frame = CGRectMake(0, 0, 80, 40);
[self.view addSubView:button];
}
- (void)buttonClick:(NSButton *)sender {
// 处理点击事件
}

2.修改文字颜色

macOS不能像iOS一样直接设置文字颜色 [button setTitleColor: forState:]

macOS的设置如下

// 1.无边框可以通过 contentTintColor 设置文字颜色
button.bordered = NO;
button.contentTintColor = NSColor.redColor;
// 2.有边框
NSMutableAttributedString *attrTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[button attributedTitle]];
[attrTitle addAttribute:NSForegroundColorAttributeName value:NSColor.redColor range:NSMakeRange(0, attrTitle.length)];
[attrTitle fixAttributesInRange:NSMakeRange(0, attrTitle.length)];
[button setAttributedTitle:attrTitle];

3.修改背景色

macOS的按钮不能像iOS一样直接设置背景颜色[self setBackgroundColor:],需要在layer层上设置

button.wantsLayer = YES;// 不设置 wantsLayer 背景色设置无效
button.layer.backgroundColor = NSColor.blueColor.CGColor;

4.让按钮点击时不高亮

[(NSButtonCell *)button.cell setHighlightsBy:NSNoCellMask];

5.鼠标悬停在按钮上出现提示文字

button.toolTip = @"瞅啥瞅,快戳啊";

6.修改按钮高度

[button setBezelStyle:NSBezelStyleRegularSquare];

四. 使用NSView创建Button

参考:《macOS开发》自定义控件之NSButton

#import <Cocoa/Cocoa.h>

NS_ASSUME_NONNULL_BEGIN

typedef enum {
FSRectCornerTopLeft = 1 << 0,
FSRectCornerTopRight = 1 << 1,
FSRectCornerBottomLeft = 1 << 2,
FSRectCornerBottomRight = 1 << 3,
FSRectCornerAllCorners = ~0UL
} FSRectCorner;

typedef enum {
FSTextAlignmentLeft = 0, //左对齐
FSTextAlignmentCenter, //居中
FSTextAlignmentRight //右对齐

}FSTextAlignment;

typedef enum {
FSTextUnderLineStyleNone = 0, //无下划线
FSTextUnderLineStyleSingle, //单下划线
FSTextUnderLineStyleDouble, //双下划线
FSTextUnderLineStyleDeleteSingle, //单删除线
FSTextUnderLineStyleDeleteDouble //双删除线

}FSTextUnderLineStyle;

@interface FSCustomBtn : NSView

@property (nullable, weak) id target;
@property (nullable) SEL action;

/// 当鼠标移动到控件时,是否显示"小手"
@property (assign, nonatomic) BOOL isHandCursor;

///圆角
@property (nonatomic, assign) CGFloat radius;
@property (nonatomic, assign) FSRectCorner rectCorners;

///按钮文字
@property (nonatomic, nullable, strong) NSString *title;
@property (nonatomic, nullable, strong) NSString *selectedTitle;

///按钮文字对齐方式
@property (nonatomic, assign) FSTextAlignment textAlignment;

///按钮文字下划线样式
@property (nonatomic, assign) FSTextUnderLineStyle textUnderLineStyle;

///按钮文字颜色
@property (nonatomic, nullable, strong) NSColor *titleColor;
@property (nonatomic, nullable, strong) NSColor *selectedTitleColor;

///按钮字体
@property (nonatomic, nullable, strong) NSFont *font;
@property (nonatomic, nullable, strong) NSFont *selectedFont;

///当背景图片存在时,背景色无效
@property (nonatomic, nullable, strong) NSImage *backgroundImage;
@property (nonatomic, nullable, strong) NSImage *selectedBackgroundImage;

///当背景图片不存在时,显示背景色
@property (nonatomic, nullable, strong) NSColor *backgroundColor;
@property (nonatomic, nullable, strong) NSColor *selectedBackgroundColor;

@end

NS_ASSUME_NONNULL_END

#import "FSCustomBtn.h"
#import <objc/message.h>

#define FSMsgSend(...) ((void (*)(void *, SEL, id))objc_msgSend)(__VA_ARGS__)
#define FSMsgTarget(target) (__bridge void *)(target)
@interface FSCustomBtn () {
NSTrackingArea *_trackingArea;
}

@property (nonatomic,assign) BOOL mouseDown;

@end

@implementation FSCustomBtn

- (void)setMouseDown:(BOOL)mouseDown {
if (_mouseDown == mouseDown) return;

_mouseDown = mouseDown;
[self setNeedsDisplay];
}

///圆角
- (void)setRectCorners:(FSRectCorner)rectCorners {
if (_rectCorners == rectCorners) return;

_rectCorners = rectCorners;
[self setNeedsDisplay];
}

///半径
- (void)setRadius:(CGFloat)radius {
if (_radius == radius) return;

_radius = radius;
[self setNeedsDisplay];
}

///按钮文字
- (void)setTitle:(NSString *)title {
if ([_title isEqualToString:title]) return;
_title = title;
[self setNeedsDisplay];
}

- (void)setSelectedTitle:(NSString *)selectedTitle {
if ([_selectedTitle isEqualToString:selectedTitle]) return;
_selectedTitle = selectedTitle;
[self setNeedsDisplay];
}

///按钮文字对齐方式
- (void)setTextAlignment:(FSTextAlignment)textAlignment {
if (_textAlignment == textAlignment) return;
_textAlignment = textAlignment;
[self setNeedsDisplay];
}

///按钮文字下划线样式
- (void)setTextUnderLineStyle:(FSTextUnderLineStyle)textUnderLineStyle {
if (_textUnderLineStyle == textUnderLineStyle) return;
_textUnderLineStyle = textUnderLineStyle;
[self setNeedsDisplay];
}

///按钮文字颜色
- (void)setTitleColor:(NSColor *)titleColor {
if (_titleColor == titleColor) return;
_titleColor = titleColor;
[self setNeedsDisplay];
}

- (void)setSelectedTitleColor:(NSColor *)selectedTitleColor {
if (_selectedTitleColor == selectedTitleColor) return;
_selectedTitleColor = selectedTitleColor;
[self setNeedsDisplay];
}

///按钮字体
- (void)setFont:(NSFont *)font {
if (_font == font) return;
_font = font;
[self setNeedsDisplay];
}

- (void)setSelectedFont:(NSFont *)selectedFont {
if (_selectedFont == selectedFont) return;
_selectedFont = selectedFont;
[self setNeedsDisplay];
}

///当背景图片存在时,背景色无效
- (void)setBackgroundImage:(NSImage *)backgroundImage {
if (_backgroundImage == backgroundImage) return;
_backgroundImage = backgroundImage;
[self setNeedsDisplay];
}

- (void)setSelectedBackgroundImage:(NSImage *)selectedBackgroundImage {
if (_selectedBackgroundImage == selectedBackgroundImage) return;
_selectedBackgroundImage = selectedBackgroundImage;
[self setNeedsDisplay];
}

///当背景图片不存在时,显示背景色
- (void)setBackgroundColor:(NSColor *)backgroundColor {
if (_backgroundColor == backgroundColor) return;
_backgroundColor = backgroundColor;
[self setNeedsDisplay];
}

- (void)setSelectedBackgroundColor:(NSColor *)selectedBackgroundColor {
if (_selectedBackgroundColor == selectedBackgroundColor) return;
_selectedBackgroundColor = selectedBackgroundColor;
[self setNeedsDisplay];
}

- (void)setNeedsDisplay {
if (self.superview) {
[self setNeedsDisplay:YES];
}
}

-(void)updateTrackingAreas {
if (_trackingArea == nil) {
_trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds
options:NSTrackingMouseEnteredAndExited|NSTrackingActiveInKeyWindow
owner:self
userInfo:nil];
[self addTrackingArea:_trackingArea];
}
}

-(void)mouseEntered:(NSEvent *)theEvent{
if (_isHandCursor == NO) return;
[[NSCursor pointingHandCursor] set];
}

-(void)mouseExited:(NSEvent *)theEvent{
if (_isHandCursor == NO) return;
[[NSCursor arrowCursor] set];
}

- (void)mouseDown:(NSEvent *)event {
NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
if (CGRectContainsPoint(self.bounds, point)) {
self.mouseDown = YES;
}
}

- (void)mouseUp:(NSEvent *)event {
if (self.mouseDown) {
self.mouseDown = NO;
[self setNeedsDisplay:YES];

NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
if (CGRectContainsPoint(self.bounds, point)) {

if (self.target && self.action && [self.target respondsToSelector:self.action]) {
FSMsgSend(FSMsgTarget(self.target), self.action, self);
}
}
}
}

- (void)drawRect:(NSRect)dirtyRect {

NSString *title = nil;
NSFont *font = nil;
NSColor *titleColor = nil;
NSColor *backgroundColor = nil;
NSImage *backgroundImage = nil;

if (self.mouseDown) {
title = self.selectedTitle;
font = self.selectedFont;
titleColor = self.selectedTitleColor;
backgroundColor = self.selectedBackgroundColor;
backgroundImage = self.selectedBackgroundImage;

if (title == nil) {
title = self.title;
}
if (font == nil) {
font = self.font;
}
if (titleColor == nil) {
titleColor = self.titleColor;
}
if (backgroundColor == nil) {
backgroundColor = self.backgroundColor;
}
if (backgroundImage == nil) {
backgroundImage = self.backgroundImage;
}
}
else {
title = self.title;
font = self.font;
titleColor = self.titleColor;
backgroundColor = self.backgroundColor;
backgroundImage = self.backgroundImage;
}

if (title == nil) {
title = @"按钮";
}
if (font == nil) {
font = [NSFont systemFontOfSize:17];
}
if (titleColor == nil) {
titleColor = [NSColor blackColor];
}
if (backgroundImage) {
backgroundColor = [NSColor colorWithPatternImage:backgroundImage];
}
else {
if (backgroundColor == nil) {
backgroundColor = [NSColor clearColor];
}
}

if (_rectCorners) {
NSBezierPath *bezierPath;
if (_rectCorners == FSRectCornerAllCorners) {
bezierPath = [NSBezierPath bezierPathWithRoundedRect:dirtyRect xRadius:_radius yRadius:_radius];
}
else {
bezierPath = [NSBezierPath bezierPath];

CGFloat topRightRadius = 0.0, topLeftRadius = 0.0, bottomLeftRadius = 0.0, bottomRightRadius = 0.0;

if (_rectCorners & FSRectCornerTopRight) {
topRightRadius = _radius;
}
if (_rectCorners & FSRectCornerTopLeft) {
topLeftRadius = _radius;
}
if (_rectCorners & FSRectCornerBottomLeft) {
bottomLeftRadius = _radius;
}
if (_rectCorners & FSRectCornerBottomRight) {
bottomRightRadius = _radius;
}

//右上
CGPoint topRightPoint = CGPointMake(dirtyRect.origin.x+dirtyRect.size.width, dirtyRect.origin.y+dirtyRect.size.height);
topRightPoint.x -= topRightRadius;
topRightPoint.y -= topRightRadius;
[bezierPath appendBezierPathWithArcWithCenter:topRightPoint radius:topRightRadius startAngle:0 endAngle:90];

//左上
CGPoint topLeftPoint = CGPointMake(dirtyRect.origin.x, dirtyRect.origin.y+dirtyRect.size.height);
topLeftPoint.x += topLeftRadius;
topLeftPoint.y -= topLeftRadius;
[bezierPath appendBezierPathWithArcWithCenter:topLeftPoint radius:topLeftRadius startAngle:90 endAngle:180];

//左下
CGPoint bottomLeftPoint = dirtyRect.origin;
bottomLeftPoint.x += bottomLeftRadius;
bottomLeftPoint.y += bottomLeftRadius;
[bezierPath appendBezierPathWithArcWithCenter:bottomLeftPoint radius:bottomLeftRadius startAngle:180 endAngle:270];

//右下
CGPoint bottomRightPoint = CGPointMake(dirtyRect.origin.x+dirtyRect.size.width, dirtyRect.origin.y);
bottomRightPoint.x -= bottomRightRadius;
bottomRightPoint.y += bottomRightRadius;
[bezierPath appendBezierPathWithArcWithCenter:bottomRightPoint radius:bottomRightRadius startAngle:270 endAngle:360];
}
[backgroundColor setFill];
[bezierPath fill];
}
else {
[backgroundColor setFill];
NSRectFill(dirtyRect);
}

if (title) {

//绘制文字
NSMutableAttributedString *attTitle = [[NSMutableAttributedString alloc] initWithString:title];

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init];
paragraphStyle.lineSpacing = 1;
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
NSDictionary *attributes = @{NSFontAttributeName:font,
NSParagraphStyleAttributeName:paragraphStyle,
NSForegroundColorAttributeName:titleColor};

[attTitle addAttributes:attributes range:NSMakeRange(0, attTitle.length)];

if (self.textUnderLineStyle == FSTextUnderLineStyleSingle) {
NSUnderlineStyle style = NSUnderlineStyleSingle;
[attTitle addAttributes:@{NSUnderlineStyleAttributeName:@(style)} range:NSMakeRange(0, attTitle.length)];
[attTitle addAttributes:@{NSUnderlineColorAttributeName:titleColor} range:NSMakeRange(0, attTitle.length)];
}
else if (self.textUnderLineStyle == FSTextUnderLineStyleDouble) {
NSUnderlineStyle style = NSUnderlineStyleDouble;
[attTitle addAttributes:@{NSUnderlineStyleAttributeName:@(style)} range:NSMakeRange(0, attTitle.length)];
[attTitle addAttributes:@{NSUnderlineColorAttributeName:titleColor} range:NSMakeRange(0, attTitle.length)];
}
else if (self.textUnderLineStyle == FSTextUnderLineStyleDeleteSingle) {
[attTitle addAttributes:@{NSStrikethroughStyleAttributeName:@(NSUnderlinePatternSolid|NSUnderlineStyleSingle),
NSStrikethroughColorAttributeName:titleColor}
range:NSMakeRange(0, attTitle.length)];
}
else if (self.textUnderLineStyle == FSTextUnderLineStyleDeleteDouble) {
[attTitle addAttributes:@{NSStrikethroughStyleAttributeName:@(NSUnderlinePatternSolid|NSUnderlineStyleDouble),
NSStrikethroughColorAttributeName:titleColor}
range:NSMakeRange(0, attTitle.length)];
}

CGSize titleSize = [attTitle.string boundingRectWithSize:CGSizeMake(self.bounds.size.width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size;

CGRect titleRect;
if (self.textAlignment == FSTextAlignmentLeft) {
titleRect = CGRectMake(0,
(self.bounds.size.height-titleSize.height)/2.0,
titleSize.width,
titleSize.height);
}
else if (self.textAlignment == FSTextAlignmentCenter) {
titleRect = CGRectMake((self.bounds.size.width-titleSize.width)/2.0,
(self.bounds.size.height-titleSize.height)/2.0,
titleSize.width,
titleSize.height);
}
else {
titleRect = CGRectMake((self.bounds.size.width-titleSize.width),
(self.bounds.size.height-titleSize.height)/2.0,
titleSize.width,
titleSize.height);
}
[attTitle drawInRect:titleRect];
}
}

- (void)removeFromSuperview {
if (_trackingArea) {
[self removeTrackingArea:_trackingArea];
}
[super removeFromSuperview];
}

@end

调用

- (void)viewDidLoad {
[super viewDidLoad];

FSCustomBtn *btn = [[FSCustomBtn alloc] initWithFrame:CGRectMake(10, 10, 100, 60)];
btn.isHandCursor = YES;
btn.target = self;
btn.backgroundColor = NSColor.whiteColor;
btn.selectedBackgroundColor = NSColor.lightGrayColor;
btn.titleColor = NSColor.redColor;
btn.selectedTitleColor = NSColor.greenColor;
btn.textAlignment = FSTextAlignmentCenter;
btn.rectCorners = FSRectCornerTopLeft | FSRectCornerBottomRight;
btn.radius = 20;
[btn setAction:@selector(btnClick:)];
[self.view addSubview:btn];
}

FSToolbarDemo

-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道