百思不得姐第4天:文本框占位文字颜色
一:設置登錄界面和注冊界面的切換
#import "CQLoginViewController.h" #import "CQCustomTextField.h" @interface CQLoginViewController () @property (weak, nonatomic) IBOutlet NSLayoutConstraint *centerTopConstraints; @property (weak, nonatomic) IBOutlet UIButton *loginbtn; @property (weak, nonatomic) IBOutlet CQCustomTextField *loginScreenField; @property (weak, nonatomic) IBOutlet CQCustomTextField *loginPhoneField; @property (weak, nonatomic) IBOutlet CQCustomTextField *registScreenField; @property (weak, nonatomic) IBOutlet CQCustomTextField *registPhoneField;@end@implementation CQLoginViewController- (void)viewDidLoad {[super viewDidLoad];//1:設置登陸注冊按鈕的圓角效果/**1:[self.loginbtn setValue:@YES forKeyPath:@"layer.masksToBounds"];[self.loginbtn setValue:@6 forKeyPath:@"layer.cornerRadius"];2: self.loginbtn.layer.masksToBounds = YES;self.loginbtn.layer.cornerRadius = 6;3:可以在xib中設置其圓角效果:設置keypath路徑即可*/}#pragma mark -- 注冊按鈕的點擊事件 - (IBAction)registBtn:(UIButton *)sender {//根據點擊的不同的按鈕來顯示登陸或是注冊的文本框/*** 1:可以根據btn.currentTile來判斷 2:根據按鈕的選中狀態來判斷 3:根據約束值來判斷*///1:先退去鍵盤 [self.view endEditing:YES];//2:偏移viewsender.selected = !sender.isSelected;self.centerTopConstraints.constant = sender.isSelected ? (- self.view.CQ_Width) : 0;[UIView animateWithDuration:0.5 animations:^{// 強制刷新 : 讓最新設置的約束值馬上應用到UI控件上// 會刷新到self.view內部的所有子控件 [self.view layoutIfNeeded];}];}#pragma mark -- 取消按鈕點擊事件 - (IBAction)cancleBtn:(UIButton *)sender {[self dismissViewControllerAnimated:YES completion:nil]; } #pragma mark -- 修改狀態欄的樣式- (UIStatusBarStyle)preferredStatusBarStyle {return UIStatusBarStyleLightContent; }#pragma mark -- 點擊空白處退去鍵盤- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {[self.view endEditing:YES]; } @end總結:1:設置登陸按鈕的圓角效果:1:直接設置按鈕的layer,若是表格視圖,不建議通過layer設置圓角效果,會很耗性能,最好是通過繪圖的方式設置圓角效果 ?2:利用kvc也可以設置圓角效果,kvc一般都是為屬性賦值,setValue forKey直接為屬性賦值,setValue forKeyPath為屬性的路徑賦值,屬性的屬性:
[self.loginbtn setValue:@YES forKeyPath:@"layer.masksToBounds"];[self.loginbtn setValue:@6 forKeyPath:@"layer.cornerRadius"];3:可以在xib中設置其圓角效果:設置keypath路徑即可 2:一個按鈕的切換:1:sender.selected = !sender.isSelected; 2:三個按鈕的切換:設置currentBtn,按鈕的三部曲
3:在xib中登陸界面,刪除左側的間距約束,拖線左側約束到控制器,根據按鈕的狀態設置左側的約束值。再在UIView的動畫里強制刷新UI: [UIView animateWithDuration:0.5 animations:^{// 強制刷新 : 讓最新設置的約束值馬上應用到UI控件上// 會刷新到self.view內部的所有子控件,立即調用layoutsubview,刷新UI視圖[self.view layoutIfNeeded];}]; 4:設置狀態欄的樣式或是顯示隱藏:就在控制器內設置: - (UIStatusBarStyle)preferredStatusBarStyle {return UIStatusBarStyleLightContent; }
二:封裝占位文字 #import <UIKit/UIKit.h>@interface UITextField (XMGExtension) /** 占位文字顏色 */ @property (nonatomic, strong) UIColor *placeholderColor; @end #import "UITextField+XMGExtension.h"static NSString * const XMGPlaceholderColorKey = @"placeholderLabel.textColor";@implementation UITextField (XMGExtension)- (void)setPlaceholderColor:(UIColor *)placeholderColor {// 提前設置占位文字, 目的 : 讓它提前創建placeholderLabelNSString *oldPlaceholder = self.placeholder;self.placeholder = @" ";self.placeholder = oldPlaceholder;// 恢復到默認的占位文字顏色if (placeholderColor == nil) {placeholderColor = [UIColor colorWithRed:0 green:0 blue:0.0980392 alpha:0.22];}// 設置占位文字顏色 [self setValue:placeholderColor forKeyPath:XMGPlaceholderColorKey]; }//- (void)setPlaceholderColor:(UIColor *)placeholderColor //{ // // 提前設置占位文字, 目的 : 讓它提前創建placeholderLabel // if (self.placeholder.length == 0) { // self.placeholder = @" "; // } // // [self setValue:placeholderColor forKeyPath:XMGPlaceholderColorKey]; //}- (UIColor *)placeholderColor {return [self valueForKeyPath:XMGPlaceholderColorKey]; }@end
總結:1:在分類中不能為類擴充屬性,在分類中以屬性定義變量,此時不會自動生成帶下劃線的成員變量,需要自己手動去實現set和get方法,若想擁有帶下劃線的成員變量,則可以static定義全局變量,在get方法中可以返回。
? ? ? ? 2:當外界傳進來參數的時候,嚴謹一些最好要先判斷外界傳進來的值是否為空,為空return返回或是設置默認值,不為空可以利用kvc為屬性賦值,在get方法中,再利用kvc?valueForKeyPath 取出值并返回
#import "CQCustomTextField.h" #import <objc/runtime.h> @implementation CQCustomTextField/*** 1:從xib中加載完成后會調用,可以在此方法中設置一些一次性代碼,類似于init方法來設置一次性代碼 2:注意的是當執行完此方法后,子控件的數組個數為0*/ - (void)awakeFromNib {//1:改變光標的顏色self.tintColor = [UIColor whiteColor];self.textColor = [UIColor whiteColor];//2:改變占位文字的默認顏色self.CQ_placeHolderColor = [UIColor lightGrayColor];}/***** @return <#return value description#>*/ - (BOOL)becomeFirstResponder {self.CQ_placeHolderColor = [UIColor whiteColor];return [super becomeFirstResponder]; }- (BOOL)resignFirstResponder {self.CQ_placeHolderColor = [UIColor lightGrayColor];return [super resignFirstResponder]; }/*** 1:可以改變Placeholder的顏色和字體大小,和內容2:在textField要顯示的時候調用 - (void)drawPlaceholderInRect:(CGRect)rect {[@"123" drawInRect:CGRectMake(5, 10, 40, self.CQ_Height - 20) withAttributes:@{NSFontAttributeName : Font(13),NSForegroundColorAttributeName : [UIColor whiteColor]}];}*//*** 1:此方法是改變占位文字的顏色:遍歷子控件,父類的指針指向子類,找到關聯的對象設置屬性 2:但是在xib中的awakeFromeNib中子控件數組為0,所以無法設置默認的placeholder的顏色- (void)layoutSubviews {[super layoutSubviews];for (UIView *view in self.subviews) {if (![view isKindOfClass:NSClassFromString(@"UITextFieldLabel")]) continue;UILabel *lable = (UILabel*)view;lable.textColor = [UIColor redColor];}}*//*** runtime:找到某個類的所有下劃線的成員變量,包括類私有的不公開的,利用kvc,valueforkeypath,將其定義的私有屬性取出,并修改其行為unsigned int count;//<#unsigned int *outCount#>:參數需要傳入一個指針Ivar *ivarList = class_copyIvarList([UITextField class], &count);for (int i = 0; i < count ; i++) {Ivar var = ivarList [i];CQLog(@"----------------------------%s", ivar_getName(var));}free(ivarList);*/@end總結:1:自定義UITextField類與xib中的文本框相關聯,在xib中,關聯自定義的類UITextField,在自定義類UITextField實現awakfromNib:?1:awakfromNib:從xib中加載完成后會調用,可以在此方法中設置一些一次性代碼,類似于init方法來設置一次性代碼 2:注意的是當執行完此方法后,子控件的數組個數為0。在此方法內設置光標的顏色和文字顏色占位文字默認顏色:? self.tintColor = [UIColor whiteColor];? self.textColor = [UIColor whiteColor];self.CQ_placeHolderColor = [UIColor lightGrayColor];
? ? ? ? 2:監聽文本框的第一響應:就重寫系統的- (BOOL)becomeFirstResponder,調用時刻 : 成為第一響應者(開始編輯\彈出鍵盤\獲得焦點),重寫此方法不要忘記調用super,否則就不能響應父類的方法,不能響應鍵盤事件彈出鍵盤。先設置占位文字顏色
- (BOOL)becomeFirstResponder
{
? ? self.placeholderColor = [UIColor whiteColor];
? ? return [super becomeFirstResponder];
}
/**
?*? 調用時刻 : 不做第一響應者(結束編輯\退出鍵盤\失去焦點)
?*/
- (BOOL)resignFirstResponder
{
? ? self.placeholderColor = [UIColor grayColor];
? ? return [super resignFirstResponder];
}
3:找到設置textField占位文字顏色的屬性:1:自定義類繼承系統的UITextField,在layoutsubView方法里看看是否能直接拿到該屬性設置 (當在方法layoutsubView設置約束的時候,配合setNeedslayout,或是layoutifNeed來更新約束)2:若不能直接拿到該屬性,則可以遍歷子控件數組并打印,拿到所有的子控件,在遍歷方法中(for in index++,for int i,enum,先做條件過濾,return,continue,或是break,拿到屬性之后(父類的指針可以指向子類),去設置屬性,找到以后并停止遍歷。)找到對應的屬性后,設置屬性值。
- (void)layoutSubviews {
??[super layoutSubviews];
?for (UIView *view in self.subviews) {
??if (![view isKindOfClass:NSClassFromString(@"UITextFieldLabel")]) continue;
??UILabel *lable = (UILabel*)view;
?lable.textColor = [UIColor redColor];
?}
?}
?4:查找系統的API,子類或是父類中有沒有方法設置占位文字的顏色,可以搜索placeHolder,或是搜索placeHolderColor,來查看。在系統的方法中可以找到drawRect方法:
?1:可以改變Placeholder的顏色和字體大小,和內容
?2:在textField要顯示的時候調用:drawRect方法都是在控件即將顯示的時候被調用
- (void)drawPlacedholderInRect:(CGRect)rect {
??[@"123" drawInRect:CGRectMake(5, 10, 40, self.CQ_Height - 20) withAttributes:@{NSFontAttributeName : Font(13),NSForegroundColorAttributeName : [UIColor whiteColor]}];
?}
5:利用runtime挖掘系統的私有屬性:
runtime:?class_copyIvarList方法找到某個類的所有下劃線的成員變量,包括類私有的不公開的,利用kvc,valueforkeypath,將其定義的私有屬性取出,并修改其行為
?unsigned int count;
//unsigned int *outCount:unsigned為無符號整型,也就是都為正數,不為負數,?int *outCount參數:outCount是一個指針,也就是需要傳入一個內存地址,也就是&count。當該方法執行完畢后,系統會根據內存地址,找到該變量,為該變量賦值
//此時的ivarList相當于一個數組,遍歷ivarList,取出的元素是Ivar類型的元素,ivar_getName(var)獲取ivar元素的屬性名字
?Ivar *ivarList = class_copyIvarList([UITextField class], &count);
??for (int? i = 0; i < count ; i++) {
?Ivar var = ivarList [i];
?CQLog(@"----------------------------%s", ivar_getName(var));
?}
?free(ivarList);//釋放ivarList
6:自定義控件繼承系統控件:利用kvc替換掉系統控件:還可以用封裝繼承,新建類繼承系統的控件,layoutSubView中可以重新布局子控件,遍歷子控件數組,找到去設置再利用kvc替換掉系統的控件
?6:補充:
1:
如圖所示,當如圖所示的按鈕時,可以讓按鈕平分整個間距。類似于底部tabBar按鈕的結構,平分整個tabBar的寬度
當設置約束的時候,1:三個等寬登高,可以同時選中設置,equalWidth,和equalHeight? 2:當去清除約束的時候,注意需要清除的是當前的約束還是全部約束。1;在xib中如何設置三個等寬登高且平分屏幕寬度。1;先設置中間按鈕的頂部間距,和高度約束,2:后兩個按鈕通過拉線設置頂部對其,確定頂部約束,再同時選中三個,右下角同時設置三個按鈕登高,等寬,在設置第一個按鈕的最左邊按鈕左間距為0,最后一個按鈕的右間距為0,同時在設置兩兩間距為0,3:如圖:當是上下左右的時候點擊小箭頭,會有和子控件的約束。(此處可以設置子控件與父控件的間距約束,如圖所示,它所設置的約束,是距離該控件最近的控件)
?
2:又有圖片又有文字的,就用button,如網易新聞導航標題。上部為圖片下部為文字的,1:就自定義button,繼承UIButton,實現button的設置title,Image的改變frame的方法。2:就自定義button,繼承UIButton:在layoutsubView里可以直接拿到btn的iamge和lable去設置frame,若是不能直接拿到,則遍歷子控件數組(遍歷條件),打印,NSClassFromstring,取出 ,停止遍歷,若是遍歷找不到,runtime,class_copyIvarlist查找其所有屬性變量,利用kvc取出或是進行賦值? 3:利用btn的內邊距,先整體內容左對齊(繼承UIControl的方法),在調節contentEdge,titleEdge,imageEdge? 2:當控件從xib中加載完成后,就會調用awakefromNib,可以在此方法中進行一些控件的固定內容或是設置屬性等工作,此方法調用完畢后子控件數組個數依然為0。3:若想自定義xib中的按鈕,則新建類繼承UIButton,先在xib中關聯類,如圖:關聯類后可以在該類中實現awakefromNib就可以直接在該類中去設置xib中的button
3:1:設置控件的frame在layoutSubView里最為嚴禁,super 調用了layoutSubView,則父類已將子控件的的frame設置好,在設置frame寫在下面是覆蓋掉super的行為,重新定義frame。2:當每次要重新布局子控件時,就要想到用到layoutsubView,配合layoutifNeeded(立即調用layoutsubView刷新frame),setNeedslayout(異步調用layoutsubView)一起使用。3:如果是更改系統控件的frame,可以通過繼承,先繼承系統的控件,重寫layoutsubView,1:直接拿到系統控件公開的屬性去設置frame ?2:若是沒有公開的屬性去設置,要拿到想要更改的子控件,可以遍歷子控件的數組,條件過濾continue,找到,重新設置frame,并停止遍歷。3:若還是找不到可以在系統API中子類或是父類中搜索相關屬性去設置 4:利用runtime的方法class_copyIvarList去拿到系統類所有帶下劃線的成員變量,利用kvc可以為屬性或是帶下劃線的成員變量賦值,還可以valurForkey或是keyPath將值取出來。
4:事件傳遞響應簡單概述:
點擊view的空白處dissMiss掉之前的控制器,實現touchBegan方法,必須該控件要開啟用戶的交互權限,且只有點擊空白處才會消失,若是點擊的是其他的按鈕,則被點擊的按鈕會響應該事件,不會實現touchbegan方法。因為的傳遞:事件的傳遞是由父控件傳遞到子控件,在傳遞過程中先看該控件能否與用戶進行交互,不能則事件傳遞直接終止,若能則會看觸摸點是不是在該ew上,兩個底層方法:pointInside,hitTest(在父類中實現這兩個方法可以返回處理該事件的view和返回觸摸點是否在自身),就這樣一級一級傳遞直到找到最合適的view來響應事件。找到最合適的view后,再看看該view能否否處理響應事件,若不能處理則交會沿著響應者鏈向上傳遞給父控件去處理。
?
5:設置xib的約束:
xib設置約束的時候:1:拉線和右下角配合使用,右下角倒數第一個有清除所有約束,清除部分約束,更新frame(改變的時候就需要更新)倒數第二個,可設置上下左右間距,寬高,等寬登高,選擇第二個,再添加約束,小箭頭也可以點擊,表示距那個控件的上下左右。倒數第三個可設置距離父控件的中心點 2:一般封裝時,會有父控件view,先固定父控件view,再往里面添加子控件,當子控件約束確定后,再去除父控件的高度,也就是讓父控件的高度等于子控件的高度,前提是設置父控件中最后一個子控件底部bottom與父控件的底部bottom的約束必須設置,這樣就可以讓父控件的高度等于子控件的高度。最好可以給xib控件寫注釋 2:背景圖片的UIImageView到底設多大??就查看背景圖片為多少像素,UIIMgaeView就設置為多大,若背景圖片很小時,則可以給UIimage寫一個分類,來拉伸圖片的寬高中心點。3:當xib設置約束的時候,也可以來到最左邊,通過寫注釋的那個,選中A將A拖向B,彈出菜單,在設置約束,設置約束的時候還可以設置對其方式,左對齊,上不對齊,右部對齊。高度為父控件的一半,先設為與父控件登高,再來到右側的約束界面,雙擊登高約束,:A等于B乘以1+0,可以改變乘以的數為0.5,則設置好了約束。如圖:底部的textField直接拷貝控件,拷貝控件的時候,只拷貝了寬高,其他約束都沒有去設置 4:
在設置textField的時候:1:可以選擇textField的style樣式,clearBtn的樣式,鍵盤的樣式,keyBoard樣式。2:xib若想完整的顯示高亮狀態下button的圖片:按鈕樣式必須為設為custom .3:給button設置圓角效果需要拿到圖層:self.loginButton.layer.cornerRadius = 5;self.loginButton.layer.masksToBounds = YES; 或是代碼利用kvc實現:setValue forKeyPath :[self.loginButton setValue:@5 forKeyPath:@"layer.cor
erRadius"];[self.loginButton setValue:@YES forKeyPath:@"layer.masksToBounds”];第二個參數為[self.loginButton的屬性。還可以在xib中設置button的圓角效果:xib中也可以實現kvc,其中在xib中控制器view的xib也可以實現lvc賦值(kvc,setValue forKeyPath,就是賦值)
?
4:
當用xib設置frame約束的時候:左邊:1:可以更改各個控件的層級關系 ,拖動 2:可以設置注釋標題,方便以后查看 3:還以按住control選中一個控件實現拉線:可以設置其左對齊,右對齊,上對齊,下對齊和其他的約束 4:在中間就設置其center屬性
水平居中或是豎直居中。
?
6:點擊已有賬號,注冊和登陸界面的左右切換:
設置的點擊注冊按鈕,左右滑動。原以為是ScrollView,其實不是,是將另一個中間的view,copy了一份,更改了約束,設置在了屏幕的右端,對于左邊的constrant約束,也可以拖線到控制器,通過更改其constranit,再在UIView的動畫里強制立即刷新,來動畫改變其左右滑動。但是左邊約束刪除,右邊的與屏幕的約束刪除約束,得刪除,要不設置了右邊的約束,當滑動的時候,view的最右邊就會永遠粘著右邊。控制器代碼:1:退出鍵盤的方式,self.view endEditing 2:取消鍵盤的第一響應者。2:按鈕在不同的狀態下顯示不同的內容,那么久去設置按鈕的不同狀態下的屬性,直接改變按鈕的狀態就可以了。3:重復點擊按鈕有不同的反應,1:可以根據按鈕的狀態去區分不同的行為,btn.selected = !btn.isselected; 2:還可以根據不同狀態下的改變值,如獲取btn不同狀態下的標題,圖片,背景圖片,或是其他的變量,來區分按鈕的不同的狀態。3:self.leftMargin為一個模型,所以不能直接放在UIView的動畫里,(UIView動畫里設置frame,前提是得是frame具體值的改變,)可以在UIView動畫外面設置模型或是frame的改變,在UIVIEW動畫的內部,調用強制刷新的方法,用self.view去調用,則會刷新整個self.view的界面? [self.view layoutIfNeeded];調用此方法會立即執行刷新操作。刷新self.view里的所有子控件。
?7:富文本的簡單使用:
一:文字的富文本屬性:
?設置textField的占位文字的顏色:
// 設置占位文字內容
@property(nullable, nonatomic,copy) ? NSString ? ? ? ? ? ? ? *placeholder;
// 設置帶有屬性的占位文字, 優先級 > placeholder
@property(nullable, nonatomic,copy) ? NSAttributedString ? ? *attributedPlaceholder;
通過富文本屬性來設置textField占位文字的顏色:
1:## NSAttributedString
- 帶有屬性的字符串, 富文本
- 由2部分組成
? ? - 文字內容 : NSString *
? ? - 文字屬性 : NSDictionary *
? ? ? ? - 文字顏色 - NSForegroundColorAttributeName
? ? ? ? - 字體大小 - NSFontAttributeName
? ? ? ? - 下劃線 - NSUnderlineStyleAttributeName
? ? ? ? - 背景色 - NSBackgroundColorAttributeName
- 初始化
?
```objc
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
attributes[NSForegroundColorAttributeName] = [UIColor yellowColor];
attributes[NSBackgroundColorAttributeName] = [UIColor redColor];
attributes[NSUnderlineStyleAttributeName] = @YES;
NSAttributedString *string = [[NSAttributedString alloc] initWithString:@"123" attributes:attributes];
```
- 使用場合
? ? - UILabel - attributedText
? ? - UITextField - attributedPlaceholder
? ? - textView-attributedText
?
2:## NSMutableAttributedString
- 繼承自NSAttributedString
- 常見方法
?
```objc
// 用set設置range范圍的屬性, 重復設置同一個范圍的屬性, 最后一次設置才是有效的(之前的設置會被覆蓋掉),而add是添加不覆蓋,set是設置會覆蓋
- (void)setAttributes:(nullable NSDictionary<NSString *, id> *)attrs range:(NSRange)range;
// 添加range范圍的屬性, 同一個范圍, 可以不斷累加屬性
- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;
- (void)addAttributes:(NSDictionary<NSString *, id> *)attrs range:(NSRange)range;
```
6:一般涉及到顯示文字的地方都可以使用富文本:例如新浪的發微博界面,titleView上下都有文字顯示,1:可以封裝一個大view,里面放兩個lable,2:也可以使用富文本,其中設置lable的換行可用\n(\n也算lable的字符串的一個字符),而且lable要是顯示多行必須設置numberoflines = 0,設置的titleView:
? UILabel *label = [[UILabel alloc] init];
? // 設置屬性文字
? NSString *text = @"你好\n哈哈哈";
? NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
? [attributedText addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:10] range:NSMakeRange(0, text.length)];
? [attributedText addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:13] range:NSMakeRange(3, 3)];//\n也算是一個字符,所以從第三個字符開始
? label.attributedText = attributedText;
? // 其他設置
? label.numberOfLines = 0;
? label.textAlignment = NSTextAlignmentCenter;
? label.frame = CGRectMake(0, 0, 100, 40);
? [self.view addSubview:label];
? self.navigationItem.titleView = label;
?
二:圖文混排圖文混排:圖片和文字混排:先定義一個大的可變的富文本對象,把整體內容切分成若干個小的富文本,分別設置好小富文本屬性后,拼接到大富文本的后面
?? UILabel *label = [[UILabel alloc] init];
?? label.frame = CGRectMake(100, 100, 200, 25);
?? label.backgroundColor = [UIColor redColor];
?? label.font = [UIFont systemFontOfSize:14];
?? [self.view addSubview:label];
?? // 圖文混排:大富文本對象
?? NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] init];
?? // 1 - 你好:設置小富文本對象并拼接到大富文本對象后面
?? NSAttributedString *first = [[NSAttributedString alloc] initWithString:@"你好"];
?? [attributedText appendAttributedString:first];
?? // 2 - 圖片
?? // 帶有圖片的附件對象
?? NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
?? attachment.image = [UIImage imageNamed:@"header_cry_icon"];
?? CGFloat lineH = label.font.lineHeight;//取出富文本中的字體高度
?? attachment.bounds = CGRectMake(0, - ((label.xmg_height - lineH) * 0.5 ), lineH, lineH);
?? // 將附件對象包裝成一個屬性文字
?? NSAttributedString *second = [NSAttributedString attributedStringWithAttachment:attachment];
?? [attributedText appendAttributedString:second];
?? // 3 - 哈哈哈
?? NSAttributedString *third = [[NSAttributedString alloc] initWithString:@"哈哈哈"];
?? [attributedText appendAttributedString:third];
?? label.attributedText = attributedText;
其中:1:求label的字體高度: CGFloat lineH = label.font.lineHeight; 是為了讓label的字體高度等于圖片的高度。bonds可調整富文本中圖片的frame,寬高為字體的寬高 2:調用系統的方法賦值,若是想在別處獲得該值,則可調用系統的get方法獲得所賦的值。3:富文本:有兩部分組成:text和屬性字典dic,分為可變和不可變,可變,則可以拼接其他富文本appendAtrtibuteString,設置富文本的內容,addAtrtibute,setAtribute,還可以根據范圍去做設置
?8:畫圖修改textfield的占位文字顏色:可以重寫drawRect 或是drawPoint 兩個方法:1:返回的rect值為textField的矩形框 2:self.font 調用的就是textField中設置font的get方法 3:self.font.lineHeight 字體高度 3:range ,rect的結構體的寫法,先定義一個rect,再賦值屬性。
- (void)drawPlaceholderInRect:(CGRect)rect {
? // 文字屬性
? ? NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
? ? attrs[NSForegroundColorAttributeName] = [UIColor whiteColor];
? ? attrs[NSFontAttributeName] = self.font;
?// drawInRect畫出占位文字
//? ? CGRect placeholderRect;
//? ? placeholderRect.size.width = rect.size.width;
//? ? placeholderRect.size.height = self.font.lineHeight;
//? ? placeholderRect.origin.x = 0;
//? ? placeholderRect.origin.y = (rect.size.height - self.font.lineHeight) * 0.5;
//? ? [self.placeholder drawInRect:placeholderRect withAttributes:attrs];
?? ?
? //?drawAtPoint畫出占位文字?
? ? CGPoint placeholderPoint = CGPointMake(0, (rect.size.height - self.font.lineHeight) * 0.5);
? ? [self.placeholder drawAtPoint:placeholderPoint withAttributes:attrs];
}
修改textField的占位文字顏色:
1:使用attributedPlaceholder? 2:- (void)drawPlaceholderInRect:(CGRect)rect;,- (void)drawPlaceholderInRect:(CGRect)rect;? 3:運行時查找系統類的私有變量:[textField setValue:[UIColor grayColor] forKeyPath:@"placeholderLabel.textColor"];
?9:scrollView的xib或是storyboard自動布局:
scrollView的自動布局(xib或是storyBoard,純xib):1:先增加一個子控件view到xib中(以后scroll
View的子控件都添加到該view中)2:設置view的約束,上下左右都為0,在設置此時該view的高度,此時該view的高度就為scrollView的contentSize 3:在設置控件的豎直滾動,就設置水平居中,水平滾動,就豎直居中 4:在設置xib時,設置父控件的高度等于內部子控件的高度,首先先添加父控件,設置好父控件的約束,在設置子控件的約束,最后來到最左邊,刪掉父控件的高度約束,再在左邊拖線,設置父控件最后一個控件的bottom和父控件的bottom的約束。4:若想設置scrolView上下左右都可以滾動,則添加一個子控件到scrollView,也是scroll唯一的子控件,設置該view上下左右的間距為0,設置寬高,不去設置水平豎直居中就可以了
#:## 在storyboard\xib中給UIScrollView子控件添加約束
- 給添加一個UIView類型的子控件A(這將是UIScrollView唯一的一個子控件)
- 設置A距離UIScrollView上下左右間距都為0
- 往A中再添加其他子控件
?

- 上下滾動(垂直滾動)
? ? - 設置A的高度(這個高度就是UIScrollView的內容高度: contentSize.height)
?
? ? 
? ? - 設置A在UIScrollView中左右居中(水平居中)
?
? ? 
- 左右滾動(水平滾動)
? ? - 設置A的寬度(這個寬度就是UIScrollView的內容寬度: contentSize.width)
?
? ? 
? ? - 設置A在UIScrollView中上下居中(垂直居中)
?
? ? 
- 上下左右滾動(水平垂直滾動)
? ? - 設置A的寬度(這個寬度就是UIScrollView的內容寬度: contentSize.width)
? ? - 設置A的高度(這個高度就是UIScrollView的內容高度: contentSize.height)
?
? ? 
? ? 
?10:實現對系統控件的監聽:查看系統控件的API中或是父類的API中,1:代理 2:繼承UIControl 的addTarget 3:系統通知? 4:kvo,主要是監聽的是屬性的改變 5:利用系統內部的某些機制,重寫系統的方法也可以實現監聽系統的行為
?11:assign 和 weak的區別:
1:報錯EXC_BAD_Access 野指針錯誤,就是說訪問了一個內存不存在,已經銷毀了的對象,會報此錯誤? 2:assin 和weak的區別:1:assin用于修飾基本數據類型 ? strong和weak用來修飾對象,2:兩者的本質區別:
@property (nonatomic, assign) XMGDog *dog;? // XMGDog *__unsafe_unretained _dog;
__unsafe_unretained的特點:
1.不是強引用, 不能保住OC對象的命
2.如果引用的OC對象銷毀了, 指針并不會被自動清空, 依然指向銷毀的對象(很容易產生野指針錯誤: EXC_BAD_ACCESS)__weak的特點:
@property (nonatomic, weak) XMGDog *dog;? // XMGDog * _Nullable __weak _dog;
1.不是強引用, 不能保住OC對象的命
2.如果引用的OC對象銷毀了, 指針會被自動清空(變為nil), 不再指向銷毀的對象(永遠不會產生野指針錯誤)
```
- 用途
? ? - assign一般用在基本數據類型上面, 比如int\double等
? ? - weak一般用在代理對象上面, 或者用來解決循環強引用的問題
- 本質區別
? ? - 速度比較: __unsafe_unretained > __weak
12:## 監聽UITextField的獲得焦點和失去焦點事件:
1:繼承UIControl的addTarget:(自己也可以監聽自己,addTarget)
[textField addTarget:target action:@selector(editingDidBegin) forControlEvents:UIControlEventEditingDidBegin];
[textField addTarget:target action:@selector(editingDidEnd) forControlEvents:UIControlEventEditingDidEnd];
UIControlEventEditingDidBegin
1.開始編輯
2.獲得焦點
3.彈出鍵盤
?
UIControlEventEditingDidEnd
1.結束編輯
2.失去焦點
3.退下鍵盤
```
?
UIControlEventEditingDidChange
文字發生改變的時候
?
2:系統控件的代理:(自己成為自己的代理,監聽自己的行為,不建議自己成為自己的代理,因為如果在外部也設置了代理,則有可能內部自己監聽自己的代理就被外部覆蓋掉了,而addTarget則可以去添加多個監聽器。add可以無限添加,而set的set方法,只能設置一個)
- delegate
?
```objc
textField.delegate = self;
?
#pragma mark - <UITextFieldDelegate>
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
?
}
?
- (void)textFieldDidEndEditing:(UITextField *)textField
{
?
}
```
3:系統的通知:
[textField addTarget:self action:@selector(test) forControlEvents:UIControlEventEditingDidBegin | UIControlEventEditingChanged];
```
- 通知:注冊觀察者,實現通知方法,dealloc中移除觀察者;其中addObserver:注冊觀察這時,object參數為誰發出的通知,一般傳nil,表示只要接收到發出的這個通知就會調用此方法,不管是誰發出的通知。若不是傳的nil,則只有后面發出的通知才會調用通知的方法
?```objc
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(beginEditing) name:UITextFieldTextDidBeginEditingNotification object:textField];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endEditing) name:UITextFieldTextDidEndEditingNotification object:textField];
?
- (void)dealloc
{
? ? [[NSNotificationCenter defaultCenter] removeObserver:self];
}
?
- (void)beginEditing
{
?
}
?
- (void)endEditing
{
?
}
```
?
使用block監聽通知:
?## 通知相關的補充
### 使用block監聽通知
1:@property(nonatomic,strong) id? observer;//必須先強引用通知
?
?2:返回值為觀察者,// object對象發出了名字為name的通知, 就在queue隊列中執行block
self.observer = [[NSNotificationCenter defaultCenter] addObserverForName:UITextFieldTextDidBeginEditingNotification object:self queue:[[NSOperationQueue alloc] init] usingBlock:^(NSNotification * _Nonnull note) {
? ? // 一旦監聽到通知, 就會執行這個block中的代碼
}];
?
//3:最后在dealloc中移除監聽
[[NSNotificationCenter defaultCenter] removeObserver:self.observer];
```
### 其他
```objc
dispatch_async(dispatch_get_global_queue(0, 0), ^{
? ? // 因為是在子線程注冊了通知監聽器, 所以beginEditing和endEditing會在子線程中執行
? ? [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(beginEditing) name:UITextFieldTextDidBeginEditingNotification object:self];
? ? [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endEditing) name:UITextFieldTextDidEndEditingNotification object:self];
});
?### 一次性通知(監聽1次后就不再監聽)
```objc
id observer = [[NSNotificationCenter defaultCenter] addObserverForName:UITextFieldTextDidBeginEditingNotification object:self queue:[[NSOperationQueue alloc] init] usingBlock:^(NSNotification * _Nonnull note) {
? // 移除通知
?[[NSNotificationCenter defaultCenter] removeObserver:observer];
}];
當對象的類型不能確定的時候,就用id去修飾此對象
利用系統內部的某些機制重寫系統的方法實現監聽:可以重寫系統的方法(不要忘記調用super的方法),來實現監聽,系統的點語法就包括了set方法和get方法,set方法賦值結束后,可以重新調用get方法來獲得該值,也可以重寫系統的某些方法,點語法的set方法,get方法,或是直接去調用的方法。重寫setfont 實現字體的設置,self.font獲得字體,重寫becomeFirstResponder等實現textfield的開始編輯光標聚焦,鍵盤彈出的監聽
?- 重寫UITextField的`becomeFirstResponder`和`resignFirstResponder`方法
```objc
/**
?*? 調用時刻 : 成為第一響應者(開始編輯\彈出鍵盤\獲得焦點)
?*/
- (BOOL)becomeFirstResponder
{
? ? return [super becomeFirstResponder];
}
?
/**
?*? 調用時刻 : 不做第一響應者(結束編輯\退出鍵盤\失去焦點)
?*/
- (BOOL)resignFirstResponder
{
? ? return [super resignFirstResponder];
}
```
?
轉載于:https://www.cnblogs.com/cqb-learner/p/5891071.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的百思不得姐第4天:文本框占位文字颜色的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: zabbix如何选择适合的监控类型(10
- 下一篇: 22 Notification 通知栏代