【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相关的常见使用场景的技术方案