【2018年中秋節良心寫作】文章將盡可能的全面介紹UITextField的所有相關知識,邏輯連貫,需要認真理解,一氣呵成。
關鍵詞:
屏幕鍵盤(onscreen keyboard)、鍵盤自定義、鍵盤類型、規范輸入源、目標動作機制(terget-action)、委托(delegate)、控件、覆蓋視圖、內建、targets和actions
UITextField類
這是一個在界面中顯示可編輯文本區域的對象。
一、概括
使用UITextField這個對象,可以收集用戶在使用屏幕鍵盤【】過程中基於文本的輸入信息。意思就是,如果你想讓用戶使用屏幕鍵盤輸入信息,那么就可以使用UITextField這個對象來獲悉用戶在鍵盤上輸入了些什么內容。屏幕鍵盤的樣式可以配置成不同的輸入類型【】來規范輸入,以適應不同的輸入場景。比如,輸入純文本、輸入電子郵件地址、輸入數字等等場景。因此,配置好鍵盤的類型,可以作為規范輸入源【】的一種手段。在輸入手機號碼的文本輸入框,則使用數字鍵盤可以更加省事,避免用戶輸入不合理的文本。UITextField對象被配置成與系統的屏幕鍵盤綁定的,即當用戶點擊UITextField對象時,UITextField就被激活,屏幕鍵盤就會自動被調用起來(從屏幕底部彈出在用戶面前,方便用戶接下來的輸入操作)。當然,剛剛說了是默認配置,也就是說,UITextField也可以使用其他非系統的屏幕鍵盤,這里涉及到的是鍵盤自定義【】方面的知識。UITextField對象使用目標動作機制【】和委托模式【】讓開發者知道UITextField的所有事件。
UITextField對象除了基本的文本編輯功能之外,開發者也可以往UITextField對象上面添加視圖,以用來展示其他的一些附加信息,或者添加一些可點擊控件【】提供給用戶做一些附加的操作。開發者可以將自定義的覆蓋視圖【】添加在UITextField對象中的各個元素上,比如書簽按鈕、搜索圖標等元素上。UITextField自身依靠這個設計,蘋果開發工程師放置了一個內建【】的覆蓋視圖在UITextField上,用它來提供“清空當前文本內容”的功能。當然,雖然是蘋果開發工程師為UITextField設計的,開發者也是可以選擇使用或者不使用這個內建的清除功能按鈕(如下圖)的。
當創建好一個UITextField對象並將它添加到界面上之后,開發者需要對這個UITextField對象進行一番配置。配置任務涉及到下面的全部或者部分:
1、為UITextField對象配置一個或多個targets和actions【】。
2、之前說到的UITextField默認使用系統鍵盤,也可以使用非系統鍵盤,但是不管使用哪種,請為該UITextField對象配置好這個鍵盤的相關屬性。
3、除了對UITextField的做一些基本的配置之外,由於該控件涉及到一些復雜的用戶交互,因此這些交互的處理等事情應該交給delegate來做。因此,請為UITextField分配好委托對象來處理重要任務。比如:(這一塊內容,需要用過UITextFieldDelegate做詳細的了解)
- 確定是否允許用戶編輯UITextField中的內容
- 驗證用戶輸入的內容
- 響應鍵盤中Return按鈕
- 將用戶輸入的內容顯示在其他控件上
4、將創建的這個UITextField對象被一個控制器對象引用。
二、關於顯示和隱藏鍵盤
當一個UITextField對象成為第一響應者【】的時候,iOS系統會自動的展示出鍵盤並且將用戶在鍵盤上的輸入和這個UITextField對象綁定在一起。這就是為什么,當用戶點擊一個UITextField對象,鍵盤彈出后,用戶在鍵盤上的輸入可以直接顯示在這個UITextFiled上面,而這一整個過程,開發者不需要做額外的關心,只需要將UITextField對象創建出來,做好上面提到的基本配置,然后添加在界面上就能完成。那么UITextField如何才能成為第一響應者呢?當用戶點擊界面上的UITextField對象的時候,這個UITextField對象就會自動的成為第一響應者。開發這也可以使用代碼讓一個UITextField對象強制成為第一響應者,調用這個UITextField的實例方法-becomeFirstResponder即可。一般是在需要用戶輸入一些信息的時候,開發者讓UITextField對象強制成為第一響應者。
提示:
鍵盤的出現有可能掩蓋界面的某些部分。開發者需要更新界面,以確保正在編輯的UITextField是可見的。監聽鍵盤的通知【】來檢測到鍵盤的出現和消失,並對界面進行一些必要的更改。
相反的,開發者也可以使用代碼讓UITextField對象強制放棄第一響應者,這樣系統就可以讓鍵盤隱藏。什么情況下,開發者會這樣做呢?比如當用戶點擊鍵盤的Return按鈕的時候,開發者需要監聽用戶的這種操作,當用戶點擊鍵盤的Return后,開發者有可能需要讓UITextField對象放棄第一響應者。iOS系統也會做自動收起鍵盤的操作,比如,當用戶點擊不支持鍵盤輸入的其他控件的時候,iOS系統會自動的讓當前的UITextField控件放棄第一響應者,隱藏(收起)鍵盤。
稍微總結下:
上面的內容要注意下順序邏輯,當UITextField成為第一響應者的時候,iOS系統會自動的彈出鍵盤;當UITextField放棄第一響應者的時候,iOS系統會自動的收起鍵盤。也就是說,成為第一響應者和彈出鍵盤,放棄第一響應者和收起鍵盤,是同時存在的,不會出現UITextField成為第一響應者,但是鍵盤不彈出等類似的情況。
然后,如何讓UITextField成為第一響應者或者放棄第一響應者呢?可以通過用戶觸發某些事件后,iOS自動的響應,也可以由開發者用代碼強制實現。
UITextField既然有編輯功能,iOS用編輯狀態【】來表示UITextField的編輯過程中的各種狀態。鍵盤的出現和消失是會影響到UITextField的編輯狀態的,並且是自動的。比如當UITextField對象成為第一響應者的時候,鍵盤自動彈出,UITextField進入編輯狀態,並且會像UITextField的委托代理發送對應的通知【】。
三、配置鍵盤的外表
開發者可以使用UITextField的UITextInputTraits協議中定義的一些屬性來自定義鍵盤。UIKit框架提供了支持用戶當前語言的標准化鍵盤,還支持用於輸入數字、URL、電子郵件地址和其他特定類型信息的專用鍵盤。開發者可以使用該協議的屬性來調整鍵盤的特性,這里所說的特性比如是:
- 鍵盤展示的樣式
- 鍵盤的自組織行為
- 鍵盤的自校正行為
- 鍵盤上Return鍵的顯示
四、響應與鍵盤相關的通知
剛剛在上面的第二點也進行了說明,鍵盤的彈出和收起是由iOS系統管理控制的,鍵盤的展示和隱藏跟隨的是第一響應者的變化。為了讓開發這能把控鍵盤的相關事件,iOS系統會發布與鍵盤相關的通知,開發者應該認真收聽這類通知,並且做好項目中的把控。這類通知包括:
- UIKeyboardWillShowNotification
- UIKeyboardDidShowNotification
- UIKeyboardWillHideNotification
- UIKeyboardDidHideNotification
- UIKeyboardWillChangeFrameNotification
- UIKeyboardDidChangeFrameNotification
在每個通知對象中都包含一個userInfo的字典對象,里面包含了鍵盤的大小(size)信息。因為鍵盤可以遮蓋住界面,因此開發者應該好好的利用這個size信息重新布局屏幕上的內容。一般可以分兩種情況,對於嵌入在滾動視圖(ScrollView或其子類)中的內容,可以將用戶正在使用的UITextField對象滾動到鍵盤之上以避免被遮住。對於其他情況,那就調整底部視圖(view對象)的位置,以避免其被鍵盤覆蓋。
五、格式化UITextField中的文本內容
UITextField提供了兩種方式供開發者使用,來設置UITextField中的文本格式:
- 首先開發者可以使用UITextField的相關屬性來控制文本格式,比如字體(font)、顏色(color)、樣式(style)。或者也可以利用NSAttributedString類為UITextField對象設置富文本字符串。
- 然后開發者也可以使用NSFormatter對象設置UITextField對象中文本格式。
像font、textColor和textAlignment這些屬性,影響的是UITextField對象中文本的外表樣式。並且作用的對象是整個文本字符串。比如開發者指定textColor為紅色,那么UITextField對象中整個字符串的字體顏色都是紅色。如果,開發者需要對TextField中的文本進行更加細膩化、或者說是局部效果的化,就需要使用NSAttributedString對象。
上面提到的NSFormatter對象,其實UITextField對象並沒有提供這方面的原生支持【】。但是,開發者可以使用UITextField的delegate來完成實時格式化字符串操作。比如使用-textField:shouldChangeCharactersInRange:replacementString:協議方法,在用戶輸入過程中驗證和做格式化操作。比如,UITextField中的文本字體顏色默認是黑色,當檢測到用戶輸入數字文本時,把數字的字符顏色格式化為紅色,起到提示作用等等場景。
六、使用覆蓋視圖(Overlay View)來編輯UITextField中的文本內容
首先需要明白的是,UITextField這個控件的內置結構,覆蓋視圖是UITextField對象的可編輯區域【】外左側和外右側顯示的小視圖。如果開發者不配置覆蓋視圖,可編輯區域將會占用覆蓋視圖的區域,一並納入可編輯區域范圍。開發者如果要使用覆蓋視圖,方法很簡單。將一個按鈕設置為UITextField對象的覆蓋視圖就行,這個按鈕一般是基於image的按鈕,比如一個書簽icon。為這個按鈕配置好target和action以響應用戶的點擊事件。下面的代碼就是為UItextField設置左邊的覆蓋視圖:
UIButton* overlayButton = [UIButton buttonWithType:UIButtonTypeCustom]; [overlayButton setImage:[UIImage imageNamed:@"bookmark"] forState:UIControlStateNormal]; [overlayButton addTarget:self action:@selector(displayBookmarks:) forControlEvents:UIControlEventTouchUpInside]; overlayButton = CGRectMake(0, 0, 28, 28); // Assign the overlay button to a stored text field self.textField.leftView = overlayButton; self.textField.leftViewMode = UITextFieldViewModeAlways;
UITextField對象自身也內建(build-in)了一個覆蓋視圖在右邊覆蓋視圖的位置上,是一個清除按鈕,這個清除按鈕可以讓用戶很方便的刪除UITextField中的所有文本內容。開發者也可以自定義右邊的覆蓋視圖,使用好rightViewMode屬性和claerButtonMode來確定好應該何時應該顯示自定義的覆蓋視圖,何時顯示清除按鈕。比如,開發者監聽如果用戶還沒有輸入任何文本的時候,右邊的覆蓋視圖顯示自定義的復制功能的按鈕,如果已經有文本內容,就讓自定義的按鈕消失,顯示的是內建的清除功能的按鈕等等情景。
七、驗證文本和管理編輯過程
UITextField是在其delegate的幫助下管理其文本的編輯過程。當用戶在與一個UITextField對象進行交互時,UITextField對象會通知它的delegate,並且可以讓delegate控制正在發生的事情。有一點尤其要注意,UITextField允許它的delegate控制正在發生的事,正在發生的事。不是發生以后在通知delegate,而是能夠直接扭轉,在發生時扭轉。說得神乎其神,其實就是在用戶-敲擊鍵盤-顯示在UITextField前,通知了delegate而已。用戶與UITextField之間的交互大致可以分為三個階段,用戶點擊UITextfield對象,讓UITextField對象啟動編輯;用戶在鍵盤上輸入的過程;用戶退出編輯。這個階段過程,UITextField都可以通過delegate與開發者進行互動,開發者可以通過delegate來防止用戶啟動或停止編輯過程,或者在鍵入文本時驗證文本。開發者還可以使用委托方法【】來執行相關任務,例如將用戶鍵入的文本顯示在界面的其他視圖上等等場景。
八、UITextField接口文件解讀
(1)驗證和處理編輯
@property(nonatomic, weak) id<UITextFieldDelegate> delegate;
👆UITextField的代理會響應編輯相關的事件。UITextFieldDelegate包含了一系列可選的方法。我反復強調過,編程這件事上,關心順序很重要!在下面要介紹的協議方法中,我會盡力的把順序理清楚。
UITextField在與用戶交互這個過程中,會把一些重要的changes(可以理解為動靜)通過delegate發布出來。當UITextField成為第一響應者並彈出鍵盤(或者是指定的其他inputView)之前,UITextField就已經開始編輯狀態了。
1、當UITextField成為第一響應者前,UITextField對象會調用代理的下面方法:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;
通過上面的這個代理方法,UITextField確定是否允許用戶接下來的鍵入操作。如果返回YES,則該UITextField對象成為第一響應者,iOS系統自動將鍵盤彈出。如果返回NO,則相當於用戶沒有點擊該UITextField對象,不會有接下來的事發生。如果開發者沒有實現這個方法,UITextField對象就默認為返回了YES。
2、接下來UITextField對象成為第一響應者,然后iOS系統為了響應,會彈出鍵盤(或者是UITextField指定的inputView對象),並且會發出UIKeyboardWillShowNotification和UIKeyboardDidShowNotification通知。如果鍵盤(或者是其他的inputView對象)已經在界面上了,則發出UIKeyboardWillChangeFrameNotification和UIKeyboardDidChangeFrameNotification通知來替代。
3、在接下來,這個UITextField對象會調用代理的下面方法,並發送UITextFieldTextDidBegineditingNotification通知:
- (void)textFieldDidBeginEditing:(UITextField *)textField;
調用這個方法的時候說明,UITextField對象剛剛已經成為第一響應者。開發者可以在這個時候更新一些狀態信息或者是執行一些其他的任務。比如,屬於覆蓋視圖的清除按鈕,就是在編輯時才可見的。
4、在編輯的過程中,下面的這個代理方法會反復被調用:
- 不管什么時候,只要UITextField中當前的文本發生了變化,UITextField就會調用代理的如下方法,並且會發出UITextFieldTextDidChangeNotification通知:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
- 當用戶點擊UITextField內建的清除按鈕的時候,UITextField會調用代理的如下方法:
- (BOOL)textFieldShouldClear:(UITextField *)textField;
- 當用戶點擊鍵盤上的Return按鈕的時候,UITextField會調用代理的如下方法:
- (BOOL)textFieldShouldReturn:(UITextField *)textField;
5、當UITextField對象將要放棄第一響應者的時候,UITextField會調用代理的如下方法:
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField;
這個方法就是,當UITextField將要放棄第一響應者前,問一下代理,是否允許UITextField對象放棄第一響應者身份。一般情況下,當用戶點擊了其他響應式的控件【】的時候,或者開發者調用UITextField的實例方法-resignFirstResponder方法,都會迫使當前的UITextField對象放棄第一響應者身份。在前面介紹UITextFieldDelegate的時候說過,開發者可以控制正在發生的事。所以,開發者可以做到不讓該UITextField對象不放棄第一響應者身份,這是可以做到的。一般情況下,都是允許其放棄的。當時也有不允許的情景,比如,開發者可以在這個協議方法中檢測文本中是否包含了一些無效的內容,如果有的話,阻止用戶切換到另一個控件,直到用戶更改完文本內容。
如果開發者不實現這個方法,默認返回YES。
最后關於這個協議方法,有一點需要注意的事,這個協議方法僅提供關於編輯是否應該結束的建議。即使返回NO,UIKit框架也有權利迫使編輯結束。比如,當這個UITextField對象從父視圖【】或者是window【】中移除的時候。
6、當UITextField放棄第一響應者后,作為響應,iOS系統會隱藏或者調整(如果用戶又去點擊另一個UITextField對象,鍵盤不會收起再彈起,而是會選擇調整,這樣的話,上面也提到過“如果鍵盤(或者是其他的inputView對象)已經在界面上了,則發出UIKeyboardWillChangeFrameNotification和UIKeyboardDidChangeFrameNotification通知來替代”)。當隱藏鍵盤的時候,iOS系統會發出UIKeyboardWillShowNotification和UIKeyboardDidShowNotification通知。
7、最后UITextField對象會調用協議的下面方法,並且發出UITextfieldTextDidEndEditingNotification通知,標志着用戶與UITextField的交互結束了:
- (void)textFieldDidEndEditing:(UITextField *)textField;
與前面第3個階段介紹的方法對應,開發者在這個方法中讓清除按鈕隱藏起來。
(2)配置UITextField的相關屬性
1、文本(iOS2.0)
@property(nonatomic, copy) NSString *text;
👆這個屬性默認值是空字符串@""。這個字符串的樣式是根據font、textColor等屬性來修飾的,上面也介紹到了,font這類屬性,修飾的是UTextField文本內容的整體,比如設置font字體為16號字體,那么UITextField文本字符串的字體都是16號字體。如果開發者想對這組文本內容進行區分對待,區分的進行樣式化,那么就要使用下面這個屬性attributedText。
2、富文本(iOS6.0)
@property(nonatomic, copy) NSAttributedString *attributedText;
👆在剛剛介紹text這個屬性的時候就已經引薦過這個屬性了,這個屬性稱之為富文本屬性,顧名思義就是這個文本不僅一個字符串屬性,里面還可以安插各種修飾屬性。開發者在平時工作中,文本展示的事情還是挺多的,所以在下意淫作者強烈推薦好好掌握它。在接下來舉例它如何使用之前,有一點需要重點說明下,就是如果對於UITextField對象同時設置了text和attributedText兩個屬性,那么UITextField展示的內容以attribuedText優先,但是如果對text屬性再一次賦予一個新的值,那么這個新的值也同樣影響到attribuedText。現在開始介紹上面這個屬性在平時工作中的使用:
3、占位字符串(iOS2.0)
@property(nonatomic, copy) NSString *placeholder;
👆這個屬性是UITextField對象中內建的(原生提供),像UITextView就沒有原生提供這個屬性。這個屬性值默認是nil,開發者設置這個屬性,可以讓UITextField文本內容為空字符串的時候,將占位字符串的內容展示出來,起到一個提示用戶輸入內容的作用。這個占位字符串的繪制屬性中的字體顏色使用的是系統默認的顏色,字體大小使用的font屬性,跟text共享一個font屬性值。
4、富文本占位字符串(iOS6.0)
@property(nonatomic, copy) NSAttributedString *attributedPlaceholder;
👆這個屬性是在iOS6出現的,placeholder屬性是在iOS2出現的。其實可以猜到這個屬性其實就是上面屬性的一個補充。就像text屬性在iOS2.0出現,富文本屬性attributedText在iOS6.0出現,也是起到一個補充的作用。
5、默認的富文本樣式(iOS7.0)
@property(nonatomic, copy) NSDictionary<NSAttributedStringKey, id> *defaultTextAttributes;
👆可以直接對UITextField對象的attributedText屬性賦值,但是在初始化attributedText對象時需要字符串參數。那么如果才能像使用font屬性一樣,先設置好富文本的樣式屬性,等到后面用戶輸入文本的時候按照事先設置好的富文本樣式進行渲染呢,那么就是這個屬性了。
6、字體(iOS2.0)
@property(nonatomic, strong) UIFont *font;
👆這個屬性作用的是整個文本信息的樣式。如果開發者不設置這個屬性,那么UITextField默認使用系統字體的粗文本樣式。尤其一點需要注意的是,這個屬性不僅作用在了text這個屬性上,上面提高的占位字符串的字體大小使用的也是這個字體號。
7、文本顏色(iOS2.0)
@property(nonatomic, strong) UIColor *textColor;
👆這個屬性作用的也是整個文本信息的樣式,設置文本字體的顏色。該屬性的默認值是黑色,該屬性值不能設置為nil,不然會引發異常。
8、文本對齊方式(iOS2.0)
@property(nonatomic) NSTextAlignment textAlignment;
👆用過word的都應該知道吧,文本對齊方式。這個屬性作用在text和placehoder兩者上,並且作用是整體屬性,因此如果開發者想區分處理樣式,請使用好富文本屬性。這個屬性默認是左對齊。
9、當前光標的富文本樣式(iOS6.0)
@property(nonatomic, copy) NSDictionary<NSAttributedStringKey, id> *typingAttributes;
👆這個屬性的使用是有前提的,首先UITextField的allowsEditingTextAttributeds是YES,即允許用戶編輯富文本信息,並且還不要設置默認的富文本樣式屬性的前提下。用戶從某一處復制了(紅色字體、16font)的富文本字符串到該UITextField中,接下來用戶自己通過鍵盤輸入文本時,使用的依然是前面的富文本樣式(紅色字體、16font)。使用過word的應該已經想到這個情景了。這個就是現在要介紹的typingAttribueds屬性。
(3)調整UITextField中文本的大小
1、是否根據UITextField中文本區域的大小自動調整font(iOS2.0)
@property(nonatomic) BOOL adjustsFontSizeToFitWidth;
👆這個屬性一般是怎么使用的呢?首先通常,UITextField中文本字體會根據font屬性進行繪制。如果這個屬性設置為YES,那么當UITextField根據font繪制出來的文本內容會超過UITextField中的文本編輯邊界矩形,那么UITextField會開始減小字體的大小,直到字符串能夠在文本編輯邊界矩形中放置得下或者直到達到最小字體為止。另外文本是沿着基線(baseline)【】縮小的。這個屬性默認值為NO,如果設置這個屬性為YES,那么還應該結合minimumFontSize(最小字體號)一起使用。
2、自動調整的最小字體
@property(nonatomic) CGFloat minimumFontSize;
👆這個屬性的默認值是0.0,因此如果開發者使用adjustsFontSizeToFitWidth屬性,就應該要對這個屬性進行賦值。另外需要注意的是,在iOS6.0+使用富文本的話,設置最小字體這個屬性,會導致整個富文本都使用這個最小化字體。
(4)管理UITextField對象的編輯行為
1、反應當前是否處於編輯狀態(iOS2.0)
@property(nonatomic, readonly, getter=isEditing) BOOL editing;
👆這個屬性是只讀,當UITextField對象開始進入編輯狀態是,這個值就是YES。當UITextField結束編輯狀態時,這個值就是NO。正如上面所說的,這些過程,UITextField會通過delegate或者是通知都會讓開發者獲知的。
2、是否在開始編輯時清除掉之前文本內容(iOS2.0)
@property(nonatomic) BOOL clearsOnBeginEditing;
👆如果這個屬性設置為YES,那么當用戶點擊UITextField對象,讓其進入編輯狀態的時候,UITextField中之前的老的文本信心全部會被清除掉。
3、是否在對UITextField插入內容時清除掉之前的文本內容(iOS6.0)
@property(nonatomic) BOOL clearsOnInsertion;
👆如果不能讓用戶長按密碼UITextField框復制密碼,並且當用戶輸入的密碼驗證錯誤后,想接着后面輸入時,直接就把原來的文本內容全部刪除掉。那么,開發者只需要將這個屬性值設置為YES就可以了。注意,這樣的話,用戶就不能對UITextField框長按顯示出長按菜單UI【】。
4、是否允許用戶編輯富文本(iOS6.0)
@property(nonatomic) BOOL allowsEditingTextAttributes;
👆 如果這個屬性之設置為YES,則用戶可以編輯富文本信息。並且,用戶可以通過復制粘貼的方式,將其他地方的富文本信息直接復制進UITextField的編輯區域,UITextField對象會保留這些樣式並顯示出來。如果設置為NO,那么用戶就從其他地方復制的富文本,UITextField不會承認。當然,這個屬性就算為NO,是不會影響到開發者用代碼設置富文本信息的。這個屬性默認值為NO。
(5)設置UITextField的背景外觀
1、樣式類型(iOS2.0)
@property(nonatomic) UITextBorderStyle borderStyle;
👆這個屬性的默認值是UITextBorderStyleNone。如果設置屬性值為UITextFieldBorderStyleRoundedRect,那么backgound(背景圖)這個屬性就會失效。UITextField本身提供了一些常用的樣式,方便開發者直接使用。
2、正常背景圖(iOS2.0)
@property(nonatomic, strong) UIImage *background;
👆當UITextField對象在enabled(可使用狀態)【】時,顯示出來的背景圖片。 這個屬性值默認為nil。當開發者設置這個屬性,就意味着不用borderstyle屬性中的樣式了,當然上面提到了,如果那個屬性值為UITextFieldBorderStyleRoundedRect那就是的該屬性無效。這個背景圖片會繪制在UITextField的底層,就像所有的背景圖片一樣,要面臨着被拉伸的情況,因此提供的圖片應該要能夠適應拉伸,或者說,做好被拉伸的准備。一般工作中,這種圖片一般都是線框背景圖,圖片中部不要有繪制的圖像,這樣在開發中,開發者可以使用將圖片中間拉伸,保證邊緣不變形的方式提供圖片給該屬性。
3、不可用狀態背景圖(iOS2.0)
@property(nonatomic, strong) UIImage *disabledBackground;
👆這個屬性需要跟上面提到的background(背景圖)屬性配套使用。如果background屬性不設置,那么單獨設置這個屬性視為無效。顧名思義,這個背景圖指的是當UITextField處於disabled狀態時的背景圖。
(6)管理UITextField的覆蓋視圖
1、標准的清除按鈕出現時機(iOS2.0)
@property(nonatomic) UITextFieldViewMode clearButtonMode;
👆UITextField對象有一個內建的清除按鈕放置在編輯區域的右邊。這個按鈕可以讓用戶能夠快速的清除掉文本內容。但是這個按鈕出現的時機,通過這個屬性讓開發者決定。這個屬性的默認值是UITextFieldViewModeNever(從不出現),但是一般的需求時當UITextField處於編輯狀態時,用戶就需要這個按鈕的存在,因此這個屬性一般設置成UITextFieldViewModeWhileEditing。
2、左覆蓋圖(iOS2.0)
@property(nonatomic, strong) UIView *leftView;
👆可以使用左覆蓋視圖來指示這個UITextField對象的作用。比如,將一個放大鏡的圖片作為左覆蓋視圖,以用來提示用戶這個UITextField對象是用來搜索的。另外,之前介紹的textAlignment屬性設置UITextField的文本內容的對齊方式,也可以設置從左到右還是從右到左的書寫習慣,這個屬性,開發者只需要放置用戶從左到右書寫習慣的圖標朝向,如果UITextField的書寫習慣變成從右到左的話,iOS系統會自動的把這個圖像的朝向翻轉過來的,關於這點開發者不用左而外的處理。另外,左覆蓋視圖的大小設置是在-leftViewRectForBounds:這個方法中設置的。因此,賦予左覆蓋視圖的圖片大小要合適,如果不合適,會自動將其縮放以適應。最后,這個屬性的類型是UIView類型,如果這是控件類型(UIControl),應該像對待所有控件一樣,設置好target和action。
3、左覆蓋視圖的出現時機(iOS2.0)
@property(nonatomic) UITextFieldViewMode leftViewMode;
👆這個熟悉過默認值是UITextFieldViewModeNever。
4、右覆蓋圖(iOS2.0)
@property(nonatomic, strong) UIView *rightView;
👆結合leftView這個屬性理解吧,一樣的。
5、右覆蓋視圖的出現時機(iOS2.0)
@property(nonatomic) UITextFieldViewMode rightViewMode;
👆結合leftViewMode這個屬性理解吧,一樣的。
(7)繪制和定位方法的重寫(⚠️下面的方法不是用來直接調用的,也不是協議方法,而是開發者子類化UITextField的時候,必要情況下,用來在實現文件中重寫的方法)
1、返回UITextField對象中文本編輯區域的CGRect。(iOS2.0)
- (CGRect)textRectForBounds:(CGRect)bounds;
👆通過接收器(OC語法中的消息接收器)【】自身的bounds,確定UITextField對象中文本編輯區域的CGRect。在該方法的默認實現下,返回的CGRect是與UITextField的邊界是一樣的,當然如果設置了覆蓋視圖,返回的CGRect是除了覆蓋視圖剩下部分的范圍。 開發者子類化UITextField后,如果對UITextField默認的這種實現方案不滿意,可以重寫這個方法,根據接收器自身的bounds來計算給出自己滿意的文本編輯區域范圍的CGRect值。
2、在指定的CGRect范圍中繪制UITextField對象中文本編輯區域。(iOS2.0)
- (void)drawTextInRect:(CGRect)rect;
👆UITextField對象在剛剛的方法1中可以得到需要在那個CGRect下繪制文本編輯區域,接下來iOS系統就會調用這個方法來開始繪制文本編輯區域了。當前圖形上下文已經配置了用於繪圖所需要的默認環境和文本顏色。在重寫這個方法中,可以進一步配置圖形上下文,然后在調用super的方法執行實際的繪圖。當然,開發者也可以完全自己使用繪圖框架【】進行繪圖渲染文本,而不調用super的方法。
3、返回UITextField對象中占位字符串文本區域的CGRect。(iOS2.0)
- (CGRect)placeholderRectForBounds:(CGRect)bounds;
👆結合上面的內容理解這個方法吧,有一點需要注意的是,如果UITextField的placeholder屬性是空字符串或者是nil的話,這個方法就不會被調用了。
4、在指定的CGRect范圍中繪制UITextField對象中占位字符串文本區域。(iOS2.0)
- (void)drawPlaceholderInRect:(CGRect)rect;
👆結合上面的內容理解這個方法即可。
5、返回UITextField整體內容的繪制CGRect。(iOS2.0)
- (CGRect)borderRectForBounds:(CGRect)bounds;
👆這個屬性怎么理解呢?我們知道,UIView的內容是繪制在UILayer(圖層)上面的,圖層的邊界默認是和UIView的邊界是重合的,但是通過這個方法,可以確定一遍圖層相對於UIView的位置。
6、返回編輯狀態下文本編輯區域的CGRect。(iOS2.0)
- (CGRect)editingRectForBounds:(CGRect)bounds;
👆這個方法要與前面的第一個方法進行區分理解,UITextField對象在編輯狀態和展示狀態下,或者說在有覆蓋視圖和沒有覆蓋視圖的情況下,文本編輯區域是不一樣的。
7、返回清除按鈕的CGRect。(iOS2.0)
- (CGRect)clearButtonRectForBounds:(CGRect)bounds;
👆清除按鈕默認是放置在UITextField對象的右邊區域位置,如果想讓清除按鈕放置在其他的位置上,開發者需要重寫這個方法並且在這個方法中返回一個新的位置。有一點需要注意的是,雖然返回的是CGRect類型,但是開發者只需要改變的是坐標orign,大小必要去更改,免得造成圖像失真。那么如何獲取大小呢,當然是通過在這個方法中調用super的這個方法,得到CGRect中的size值。畢竟清除按鈕中的“清除icon”不是開發者提供的。
8、返回左覆蓋視圖的CGRect。(iOS2.0)
- (CGRect)leftViewRectForBounds:(CGRect)bounds;
👆左覆蓋視圖和右覆蓋視圖的位置都是有默認的位置的,如果有特殊的需求開發者需要改變它們的位置或者大小,那么就要重寫這個方法並且在這個方法中返回一個新的CGRect值。注意,由於左右覆蓋視圖的圖片是可以通過leftView和rightView這個屬性提供的,因此這個方法返回的CGRect不用像剛剛講到的清除按鈕的CGRect一樣,是既可以指定新的坐標,也可以指定新的size的,但是為了不讓圖片失真,開發者還是要注意這里提供的size,要和leftView屬性提供的image的大小要匹配。
9、返回右覆蓋視圖的CGRect。(iOS2.0)
- (CGRect)rightViewRectForBounds:(CGRect)bounds;
👆參考剛剛上面講解到方法理解吧。在這里補充一點,比如左覆蓋視圖的出現需要讓開發者設置好左覆蓋視圖的圖片、出現時機的設置、左覆蓋視圖的CGRect(同時還要確保可編輯區域的CGRect不要覆蓋到覆蓋視圖的區域)、時機的出現等等要求。
(8)替換系統提供的輸入視圖(inputView)
1、輸入視圖(iOS3.2)
@property(readwrite, strong) UIView *inputView;
👆在文章的上面提到過,當UITextField對象成為第一響應者的時候,iOS系統會自動的將鍵盤彈出。彈出的是系統標准的鍵盤,如果開發者需要使用自定義的鍵盤,最好是通過這個屬性來操作,雖然就算不用這個屬性也完全是可以實現的,但是開發者就需要做很多附帶的操作了,比如,監聽UITextField的點擊事件、自定義鍵盤的動畫彈出、發出各種通知等等。inputView這個屬性值默認是nil,這樣當UITextField對象成為第一響應者的時候系統使用的就是標准的系統鍵盤。
2、輸入視圖上的附件視圖(iOS3.2)
@property(readwrite, strong) UIView *inputAccessoryView;
👆彈出的鍵盤視圖上面的一塊空間是可以被開發者使用的,不管是使用系統標准鍵盤還是使用自定義鍵盤,這個屬性都可以實現。使用這個屬性將自定義工具欄附加到鍵盤視圖上面一塊區域,方面用戶的更多便捷操作。
九、與UITextField相關的常見使用場景的技術方案