回首個(gè)??的20XX年!
抱歉,羅老師!再來一下~
回首個(gè)??的20XX年。。
前期發(fā)布應(yīng)用后,主要維護(hù)和更新App(悲傷辣么大~)。。后期又開始做Mac App!
本來想寫一篇叫《Mac App常用的控件》的文章!結(jié)果整理發(fā)現(xiàn)一個(gè)NSButton都有點(diǎn)讓人頭痛。。
所以這篇文章就講講NSButton及其相應(yīng)的應(yīng)用!
最近這段時(shí)間一直在做Mac App。Mac App被叫做“Cocoa App”!(我習(xí)慣叫Mac App!)
創(chuàng)建時(shí),長這樣:
工程創(chuàng)建好,創(chuàng)建2個(gè)button,看看效果~:
NSButton * btn1 = [[NSButton alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)];
[self.view addSubview:btn1];
[btn1 setTitle:@"dadfjkl"];
btn1.wantsLayer = YES;
btn1.layer.backgroundColor = [NSColor redColor].CGColor;
NSButton * btn2 = [[NSButton alloc] initWithFrame:NSMakeRect(200, 100, 100, 20)];
[self.view addSubview:btn2];
[btn2 setTitle:@"sdafd"];
btn2.wantsLayer = YES;
btn2.layer.backgroundColor = [NSColor cyanColor].CGColor;
運(yùn)行的效果:
OK,開始研究其特征,咱就創(chuàng)建一堆button:
屬性 - 邊框樣式NSBezelStyle
:
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 NS_ENUM_AVAILABLE_MAC(10_7) = 15,
};
將title設(shè)置為@"":
CGFloat margin = 2.f;
CGFloat total_W = NSWidth([self.view frame]);
for (int i = 0; i < 13; i ++) {
CGFloat w = (total_W - margin*(CGFloat)(13-1))/(CGFloat)13;
CGFloat x = i*(w+margin);
CGFloat y = 5.f;
CGFloat h = 20.f;
NSButton * btn = [[NSButton alloc] initWithFrame:NSMakeRect(x, y, w, h)];
[self.view addSubview:btn];
[btn setTitle:@""];
switch (i) {
case 0:{
[btn setBezelStyle:NSBezelStyleRounded];
} break;
case 1:{
[btn setBezelStyle:NSBezelStyleRegularSquare];
} break;
case 2:{
[btn setBezelStyle:NSBezelStyleDisclosure];
} break;
case 3:{
[btn setBezelStyle:NSBezelStyleShadowlessSquare];
} break;
case 4:{
[btn setBezelStyle:NSBezelStyleCircular];
} break;
case 5:{
[btn setBezelStyle:NSBezelStyleTexturedSquare];
} break;
case 6:{
[btn setBezelStyle:NSBezelStyleHelpButton];
} break;
case 7:{
[btn setBezelStyle:NSBezelStyleSmallSquare];
} break;
case 8:{
[btn setBezelStyle:NSBezelStyleTexturedRounded];
} break;
case 9:{
[btn setBezelStyle:NSBezelStyleRoundRect];
} break;
case 10:{
[btn setBezelStyle:NSBezelStyleRecessed];
} break;
case 11:{
[btn setBezelStyle:NSBezelStyleRoundedDisclosure];
} break;
case 12:{
[btn setBezelStyle:NSBezelStyleInline];
} break;
default:
break;
}
}
運(yùn)行的效果:
注釋掉“
[btn setTitle:@""];
”與 將title設(shè)置為@"" 的對(duì)比:(展示標(biāo)題與否)
點(diǎn)擊效果:
屬性 - 按鈕樣式NSButtonType
:
typedef NS_ENUM(NSUInteger, NSButtonType) {
NSButtonTypeMomentaryLight = 0,
NSButtonTypePushOnPushOff = 1,
NSButtonTypeToggle = 2,
NSButtonTypeSwitch = 3,
NSButtonTypeRadio = 4,
NSButtonTypeMomentaryChange = 5,
NSButtonTypeOnOff = 6,
NSButtonTypeMomentaryPushIn = 7,
NSButtonTypeAccelerator NS_ENUM_AVAILABLE_MAC(10_10_3) = 8,
NSButtonTypeMultiLevelAccelerator NS_ENUM_AVAILABLE_MAC(10_10_3) = 9,
};
咱還是創(chuàng)建一堆button:
CGFloat margin = 2.f;
CGFloat total_W = NSWidth([self.view frame]);
for (int i = 0; i < 10; i ++) {
CGFloat w = (total_W - margin*(CGFloat)(10-1))/(CGFloat)10;
CGFloat x = i*(w+margin);
CGFloat y = 5.f;
CGFloat h = 20.f;
NSButton * btn = [[NSButton alloc] initWithFrame:NSMakeRect(x, y, w, h)];
[self.view addSubview:btn];
btn.wantsLayer = YES;
btn.layer.backgroundColor = [NSColor redColor].CGColor;//背景色為紅色
[btn setBezelStyle:NSRoundedBezelStyle];//設(shè)置邊框樣式為‘圓狀曲線’
[btn setTitle:@""];
switch (i) {
case 0:{
[btn setButtonType:NSButtonTypeMomentaryLight];
} break;
case 1:{
[btn setButtonType:NSButtonTypePushOnPushOff];
} break;
case 2:{
[btn setButtonType:NSButtonTypeToggle];
} break;
case 3:{
[btn setButtonType:NSButtonTypeSwitch];
} break;
case 4:{
[btn setButtonType:NSButtonTypeRadio];
} break;
case 5:{
[btn setButtonType:NSButtonTypeMomentaryChange];
} break;
case 6:{
[btn setButtonType:NSButtonTypeOnOff];
} break;
case 7:{
[btn setButtonType:NSButtonTypeMomentaryPushIn];
} break;
case 8:{
[btn setButtonType:NSButtonTypeAccelerator];
} break;
case 9:{
[btn setButtonType:NSButtonTypeMultiLevelAccelerator];
} break;
default:
break;
}
}
運(yùn)行的效果:
注釋掉“
[btn setTitle:@""];
”與 將title設(shè)置為@"" 的對(duì)比:(展示標(biāo)題與否)
點(diǎn)擊效果:
總結(jié)
0 (
NSButtonTypeMomentaryLight
)、
2 (NSButtonTypeToggle
)、
7 (NSButtonTypeMomentaryPushIn
)
8 (NSButtonTypeAccelerator
)
9 (NSButtonTypeMultiLevelAccelerator
):
點(diǎn)擊時(shí)會(huì)有 高亮的選中色(高亮狀態(tài))。1 (
NSButtonTypePushOnPushOff
)、
6 (NSButtonTypeOnOff
):
選中狀態(tài)是藍(lán)色,再次點(diǎn)擊會(huì)恢復(fù)到原本的顏色。3 (
NSButtonTypeSwitch
):
選中后,可取消選中(設(shè)置state)!(適合做多選。)4 (
NSButtonTypeRadio
) :
選中后,不能取消選中(代碼上設(shè)置state,可取消選中)!(適合做單選。)5 (
NSButtonTypeMomentaryChange
):
點(diǎn)擊時(shí)會(huì)有高亮狀態(tài)(文字閃爍),但沒有 高亮的選中色。
§§§§§§§§不設(shè)置邊框樣式
注釋掉“[btn setBezelStyle:NSRoundedBezelStyle];//設(shè)置邊框樣式為‘圓狀曲線’
”
對(duì)應(yīng)的效果:注釋掉“[btn setTitle:@""];”注釋掉“
[btn setTitle:@""];
”與 將title設(shè)置為@"" 的對(duì)比:(展示標(biāo)題與否)點(diǎn)擊效果:
基本的使用如上,達(dá)到各種效果就需要組合屬性來使用(當(dāng)然還有其他屬性)!
(2019.02.13)
(2021.05.02) 以上代碼的效果肯定與現(xiàn)在編譯you差異,沒心思去改了,請(qǐng)見諒~??
????!拖泥馬這么久,再寫簡書。。
設(shè)置按鈕的背景色 |
---|
Mac的控件,只能在layer層設(shè)置顏色 — 設(shè)置wantsLayer 為YES,再通過.layer.backgroundColor 設(shè)置顏色 |
NSButton * backColorBtn = [[NSButton alloc] initWithFrame:CGRectMake(100, 120, 100, 100)];
[self.view addSubview:backColorBtn];
backColorBtn.wantsLayer = YES;
backColorBtn.layer.backgroundColor = [NSColor redColor].CGColor;
[backColorBtn setBezelStyle:NSBezelStyleDisclosure];//格式1
//[backColorBtn setBezelStyle:NSBezelStyleCircular];//格式2
//[backColorBtn setBezelStyle:NSBezelStyleHelpButton];//格式3
[backColorBtn setTitle:@"標(biāo)題"];
三種可看背景色的邊框格式對(duì)應(yīng)造型:NSBezelStyleDisclosure
、NSBezelStyleCircular
、NSBezelStyleHelpButton
系統(tǒng)的Button造型不純(控件NSButton系統(tǒng)自帶的附帶信息多)!但是設(shè)置按鈕的背景色實(shí)際使用的意義不大!
非要實(shí)現(xiàn)設(shè)置按鈕的背景色:可以在NSButton上添加一個(gè)視圖(NSView \ NSImageView均可以)覆蓋掉就好了(再封裝個(gè)控件就好了),反正是不會(huì)響應(yīng)鼠標(biāo)事件的視圖就可以!
NSView * addedV = [[NSView alloc] initWithFrame:backColorBtn.bounds]; addedV.wantsLayer = YES; addedV.layer.backgroundColor = backColorBtn.layer.backgroundColor; [backColorBtn addSubview:addedV]; [backColorBtn setTarget:self]; [backColorBtn setAction:@selector(clickBackColorBtn:)];
事件的響應(yīng):
-(void)clickBackColorBtn:(NSButton *)btn { NSLog(@"clickBackColorBtn"); }
效果:交互無問題,美觀有問題(有一個(gè)標(biāo)題)!
有一個(gè)標(biāo)題,影響美觀為了到達(dá)如下效果:
純色按鈕
- 解決方法1:把
[backColorBtn setTitle:@"標(biāo)題"];
替換為[backColorBtn setTitle:@""];
!直接不展示標(biāo)題即可!- 解決方法2:添加
[backColorBtn setImage:[NSImage imageNamed:@"gyh_btn_nor"]];
這一句代碼,設(shè)置一張圖片覆蓋掉系統(tǒng)的控件!(需保證添加的圖片尺寸能覆蓋完系統(tǒng)的控件,但又不超出該按鈕的范圍)
為Button添加圖片,進(jìn)行覆蓋
???? 達(dá)到最終效果就廢了這么多幺蛾子。。(再封裝一下就可以搞個(gè)‘生成純色按鈕’的方法)當(dāng)然這是我自己的的代碼!有熟悉Mac OS開發(fā)的朋友有更好的方法來實(shí)現(xiàn),可以交流一下!
搞這個(gè)玩意兒,意義真不大!
說意義不大的原因是:開發(fā)的軟件產(chǎn)品一般不會(huì)用到純色按鈕的情況!
軟件產(chǎn)品中大多可能用到無色(ClearColor)加上按鈕的圖片!
設(shè)置按鈕的標(biāo)題顏色及字體 |
---|
(原理:為NSButton設(shè)置富文本屬性—attributedTitle ) |
為NSButton添加類別(NSButton+SetTitleFont),實(shí)現(xiàn)如下:
#import "NSButton+SetTitleFont.h"
@implementation NSButton (SetTitleFont)
-(void)setTitleColorToColor:(NSColor *)color andFontNum:(CGFloat)FontNum isBold:(BOOL)isBold {
NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
[paraStyle setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]];
[paraStyle setAlignment:NSTextAlignmentCenter];
//[paraStyle setLineBreakMode:NSLineBreakByTruncatingTail];
NSFont * useFont = [NSFont systemFontOfSize:FontNum];
if (isBold == YES) {
useFont = [NSFont boldSystemFontOfSize:FontNum];
}
NSDictionary *attrButton = @{
NSFontAttributeName : useFont,
NSForegroundColorAttributeName : color,
NSParagraphStyleAttributeName : paraStyle
};
NSAttributedString * btnString = [[NSAttributedString alloc] initWithString:self.title attributes:attrButton];
self.attributedTitle = btnString;
}
使用如下:
NSButton * backColorBtn = [[NSButton alloc] initWithFrame:CGRectMake(100, 120, 150, 150)];
[self.view addSubview:backColorBtn];
[backColorBtn setTitle:@"標(biāo)題title"];
[backColorBtn setTitleColorToColor:[NSColor blueColor] andFontNum:15.f isBold:YES];
效果如下:(藍(lán)色、15號(hào)字體、加粗)
設(shè)置按鈕的圖片、按鈕狀態(tài)的控制 |
---|
(setImage: 方法-設(shè)置普通狀態(tài)的圖片 和 setAlternateImage: 方法-設(shè)置選中狀態(tài)的圖片) |
常用狀態(tài)—NSControlStateValueOff 、NSControlStateValueOn
|
實(shí)現(xiàn)功能:有一排操作按鈕——前兩項(xiàng)的選中只能是單選,最后一項(xiàng)點(diǎn)擊鼠標(biāo)后僅響應(yīng)事件!
圖片素材添加上:
設(shè)置全局變量:
@implementation ViewController {
NSButton * _select_lineBtn;//選中的按鈕
NSArray * _titleArr;//所有項(xiàng)目的數(shù)組
}
實(shí)現(xiàn)功能:
_titleArr = @[@"文件",@"txt",@"goyohol"];//所有項(xiàng)目的數(shù)組
NSArray * norImgArr = @[@"file_btn_nor",@"txt_btn_nor",@"gyh_btn_nor"];//普通狀態(tài)的圖片
NSArray * selImgArr = @[@"file_btn_sel",@"txt_btn_sel",@"gyh_btn_sel"];//選中時(shí)的圖片
float btn_Y = 20.f;
float btn_Width = 100.f;
float margin = btn_Width*(15.f/200.f);
for (int i = 0; i < _titleArr.count; i++) {
float x = margin + i*(margin+btn_Width);
NSButton * lineBtn = [[NSButton alloc] initWithFrame:CGRectMake(x, btn_Y, btn_Width, btn_Width)];
[self.view addSubview:lineBtn];
lineBtn.tag = 100 + I;
lineBtn.layer.backgroundColor = [NSColor clearColor].CGColor;
[lineBtn setTitle:@""];//[lineBtn setTitle:titleArr[i] ];//標(biāo)題
[lineBtn setToolTip:_titleArr[i] ];//懸停的提示
[lineBtn setBezelStyle:NSBezelStyleCircular];
lineBtn.bordered = NO;//設(shè)置為NO,點(diǎn)擊不響應(yīng)
NSString * imgStr = norImgArr[I];
[lineBtn setImage:[NSImage imageNamed:imgStr]];
NSString * sel_imgStr = selImgArr[I];
[lineBtn setAlternateImage:[NSImage imageNamed:sel_imgStr]];
if (i == _titleArr.count - 1) {
NSString * down_imgStr = selImgArr[I];
[lineBtn setAlternateImage:[NSImage imageNamed:down_imgStr]];
}
[lineBtn setImagePosition:NSImageOnly];
[lineBtn setButtonType:NSButtonTypeSwitch ];//按鈕類型(可多選)
[lineBtn setTarget:self];
[lineBtn setAction:@selector(clickTheButton:)];
lineBtn.layer.masksToBounds = YES;
lineBtn.layer.cornerRadius = btn_Width/2.f;
if (i == 0) { //第一項(xiàng) 設(shè)置為選中
lineBtn.state = NSControlStateValueOn;
_select_lineBtn = lineBtn;//設(shè)置為 選中的按鈕
}
}
點(diǎn)擊這一排按鈕的響應(yīng):
/** MARK:點(diǎn)擊一排的按鈕 */
-(void)clickTheButton:(NSButton *)sender {
long selectTag = sender.tag - 100;
if (selectTag != _titleArr.count - 1) {
_select_lineBtn.state = NSControlStateValueOff;//設(shè)置為非選中 選中的按鈕(一排)
sender.state = NSControlStateValueOn;
_select_lineBtn = sender;//設(shè)置為 選中的按鈕(一排)
} else { //最后一項(xiàng) 不可變?yōu)檫x中狀態(tài)
sender.state = NSControlStateValueOff;
}
}
效果: 前兩項(xiàng)的選中只能是單選,最后一項(xiàng)點(diǎn)擊鼠標(biāo)后僅響應(yīng)點(diǎn)擊事件!
Tips:設(shè)置“toolTip”屬性——“
setToolTip:
”方法:(鼠標(biāo)懸停的提示,目前看來大部分控件都有此屬性)設(shè)置“toolTip”屬性后
常見 可選中(背景圖)、含標(biāo)題的按鈕 |
---|
圖片放在最下面-setImagePosition:NSImageOverlaps 、圖片自動(dòng)調(diào)整尺寸-setImageScaling:NSImageScaleAxesIndependently
|
圖片素材:
執(zhí)行代碼:
NSButton * selectBtn = [[NSButton alloc] initWithFrame:NSMakeRect(100, 100, 150, 50)];
[self.view addSubview:selectBtn];
[selectBtn setTitle:@"標(biāo)題"];
[selectBtn setTitleColorToColor:[NSColor blackColor] andFontNum:15.f isBold:YES];
[selectBtn setBezelStyle:NSBezelStyleCircular];
[selectBtn setButtonType:NSButtonTypeSwitch ]; //按鈕類型(可多選)
[selectBtn setImagePosition:NSImageOverlaps]; //圖片放在最下面
[selectBtn setImageScaling:NSImageScaleAxesIndependently]; //圖片自動(dòng)調(diào)整尺寸
[selectBtn setImage:[NSImage imageNamed:@"unit_btn_nor"]];
[selectBtn setAlternateImage:[NSImage imageNamed:@"unit_btn_sel"]];
效果:單擊可切換按鈕的狀態(tài)—選中/未選中
NSButton內(nèi)部的層次關(guān)系:
未選中狀態(tài)選中狀態(tài)
按下不變色,標(biāo)題會(huì)改變 |
---|
關(guān)鍵代碼:btn.cell setHighlightsBy:NSNoCellMask !(但不能調(diào)用setButtonType: 方法,設(shè)置按鈕類型為NSButtonTypeOnOff 、NSButtonTypePushOnPushOff 這種開關(guān)狀態(tài)類型! |
NSButton * backGroundBtn = [[NSButton alloc] initWithFrame:NSMakeRect(100, 100, 100, 50)];
[self.view addSubview:backGroundBtn];
[backGroundBtn setTitle:@"未選中"];
[backGroundBtn setTarget:self]; [backGroundBtn setAction:@selector(clickToBackGroundBtn:)];
[backGroundBtn setBezelStyle:NSBezelStyleRegularSquare];
[backGroundBtn.cell setHighlightsBy:NSNoCellMask];//設(shè)置高亮狀態(tài):按下 不變色
按鈕的響應(yīng)方法:
-(void)clickToBackGroundBtn:(NSButton *)btn {
NSString * logStr = @"";
switch (btn.state) {
case NSControlStateValueMixed:
logStr = @"NSControlStateValueMixed";
break;
case NSControlStateValueOff:
logStr = @"NSControlStateValueOff";
break;
case NSControlStateValueOn:
logStr = @"NSControlStateValueOn";
break;
default:
break;
}
NSLog(@"btn.state:%@",logStr);
if (btn.state == NSControlStateValueOn) {
[btn setTitle:@"未選中"];
} else {
[btn setTitle:@"選中"];
}
}
效果:按鈕按下不變色,標(biāo)題會(huì)根據(jù)按鈕狀態(tài)而改變!
Tips:按鈕A擁有按下不變色的特性,還可以將按鈕A作為(不變色的)絕緣的背景視圖!
由于按鈕A隔絕了其他鼠標(biāo)事件的傳遞!所以點(diǎn)擊按鈕A(或在按鈕A上操作子控件時(shí)誤觸按鈕A),不會(huì)影響按鈕A的父視圖(鼠標(biāo)事件將不會(huì)傳遞到父視圖)!
按鈕類型(單選) |
---|
調(diào)用setButtonType: 方法,設(shè)置按鈕類型為NSButtonTypeRadio !再對(duì)按鈕的狀態(tài)進(jìn)行控制! |
界面布局代碼:
//"暗黑模式:"Label
CGFloat DarkMode_LB_X = 10.f, DarkMode_LB_Y = 10.f, DarkMode_LB_W = 70.f, DarkMode_LB_H = 20.f;
NSTextField * _DarkMode_Label = [[NSTextField alloc] initWithFrame:NSMakeRect(DarkMode_LB_X, DarkMode_LB_Y, DarkMode_LB_W, DarkMode_LB_H)];
[self.view addSubview:_DarkMode_Label];
_DarkMode_Label.backgroundColor = [NSColor clearColor];
_DarkMode_Label.editable = NO;
_DarkMode_Label.bordered = NO;
_DarkMode_Label.alignment = NSTextAlignmentLeft;
_DarkMode_Label.stringValue = @"暗黑模式:";
_DarkMode_Label.font = [NSFont systemFontOfSize:13.f];
//"開啟"按鈕(“暗黑模式”)
CGFloat selectBtn_W = 50.f; CGFloat selectBtn_H = 20.f;
CGFloat on_DarkMode_Btn_X = CGRectGetMaxX(_DarkMode_Label.frame);
CGFloat on_DarkMode_Btn_Y = CGRectGetMinY(_DarkMode_Label.frame);
_on_DarkMode_Btn = [[NSButton alloc] initWithFrame:NSMakeRect(on_DarkMode_Btn_X, on_DarkMode_Btn_Y, selectBtn_W, selectBtn_H)];
[self.view addSubview:_on_DarkMode_Btn]; //"開啟"按鈕(“暗黑模式”)
[_on_DarkMode_Btn setTitle:@"開啟"];
[_on_DarkMode_Btn setButtonType:NSButtonTypeRadio];//按鈕類型(單選)
[_on_DarkMode_Btn setTarget:self];
[_on_DarkMode_Btn setAction:@selector(clickToTurnOnDarkModeButtonSelect)]; //"開啟"按鈕(“暗黑模式”)-選中
_on_DarkMode_Btn.state = NSControlStateValueOn;
//"關(guān)閉"按鈕(“暗黑模式”)
CGFloat off_DarkMode_Btn_X = CGRectGetMaxX(_on_DarkMode_Btn.frame);
CGFloat off_DarkMode_Btn_Y = CGRectGetMinY(_on_DarkMode_Btn.frame);
_off_DarkMode_Btn = [[NSButton alloc] initWithFrame:NSMakeRect(off_DarkMode_Btn_X, off_DarkMode_Btn_Y, selectBtn_W, selectBtn_H)];
[self.view addSubview:_off_DarkMode_Btn]; //"關(guān)閉"按鈕(“暗黑模式”)
[_off_DarkMode_Btn setTitle:@"關(guān)閉"];
[_off_DarkMode_Btn setButtonType:NSButtonTypeRadio];//按鈕類型(單選)
[_off_DarkMode_Btn setTarget:self];
[_off_DarkMode_Btn setAction:@selector(clickToTurnOffDarkModeButtonDisSelect)];//"關(guān)閉"按鈕(“暗黑模式”)-選中
_off_DarkMode_Btn.state = NSControlStateValueOff;
按鈕的響應(yīng)事件:
-(void)clickToTurnOnDarkModeButtonSelect { //"開啟"按鈕(“暗黑模式”)-選中
_on_DarkMode_Btn.state = NSControlStateValueOn;
_off_DarkMode_Btn.state = NSControlStateValueOff;
}
-(void)clickToTurnOffDarkModeButtonDisSelect { //"關(guān)閉"按鈕(“暗黑模式”)-選中
_on_DarkMode_Btn.state = NSControlStateValueOff;
_off_DarkMode_Btn.state = NSControlStateValueOn;
}
效果:"開啟"或"關(guān)閉"只能選中一個(gè)!
后續(xù)有關(guān)于NSButton總結(jié)的內(nèi)容,再更新吧~??