本章主要讲述文本显示及输入相关控件UILabel、UITextFiled、UITextView、UISearchBar,其他相关的UISearchController、UISearchDisplayController以后再学习
UILabel标签
初始化
UILabel没有特有的初始化器,继承自UIView,用frame初始化
let label = UILabel(frame: CGRect(x: 15, y: 200, width: 100, height: 20))
重要属性
继承自UIView,相关属性不再赘述
- text 显示文本,Optional(String)类型 default is nil
- font 文本字体,default is nil(system font 17 plain)
- textColor 文本颜色,default is labelColor
- shadowColor 阴影颜色 default is nil(no shadow)
- shadowOffset 阴影偏移 default is CGSizeMake(0, -1) -- a top shadow
- textAlignment NSTextAlignment枚举类型 文本对齐方式 default is natural
- lineBreakMode NSLineBreakMode枚举类型 UILabel省略号位置 default is byTruncatingTail
- attributedText 富文本 后面单独列出来讲述
- highlightedTextColor 这个是留作以后开发UILabel的子类用于点击高亮状态提前在基类保留的属性 default is nil
- isHighlighted 是否为高亮状态 default is no
- isUserInteractionEnabled 用户交互 default is no
- isEnabled default is YES. Label的绘制方式,将它设置为NO时文本变暗,表示没有激活,这时设置颜色值是无效
- numberOfLines 显示行数 default is 1(single line)
- adjustsFontSizeToFitWidth 设置字体大小适应label宽度
- minimumScaleFactor 设置最小收缩比例 default is 0.0
- allowsDefaultTighteningForTruncation 改变字母之间的间距来适应Label大小
- preferredMaxLayoutWidth 最大约束宽
其中两个枚举 NSTextAlignment 与 NSLineBreakMode:
- NSTextAlignment:
- left 左对齐
- center 居中对齐
- right 右对齐
- justified 段落最后一行自然对齐
- natural 指示脚本的默认对齐方式
- NSLineBreakMode
- byWordWrapping // 以单词为单位换行,以单词为单位截断
- byCharWrapping // 以字符为单位换行,以字符为单位截断
- byClipping // 剪切与文本宽度相同的内
容长度,后半部分直接删除 - byTruncatingHead // 行首截断 如: "...wxyz"
- byTruncatingTail // 行尾截断 如: "abcd..."
- byTruncatingMiddle // 中间截断 如: "ab...yz"
富文本NSAttributedString
可用于编辑的为NSAttributedString子类NSMutableAttributedString
常用方法主要为:
//添加单个属性
func addAttribute(_ name: NSAttributedString.Key, value: Any, range: NSRange)
//添加多个属性
func addAttributes(_ attrs: [NSAttributedString.Key : Any] = [:], range: NSRange)
//删除属性
func removeAttribute(_ name: NSAttributedString.Key, range: NSRange)
//替换富文本
func replaceCharacters(in range: NSRange, with attrString: NSAttributedString)//添加属性
//插入富文本
func insert(_ attrString: NSAttributedString, at loc: Int)
//追加富文本
func append(_ attrString: NSAttributedString)
//删除范围内的富文本
func deleteCharacters(in range: NSRange)
常用的NSMutableAttributedString使用示例:
let titleLabel = UILabel(frame: CGRect(x: 15, y: 150, width: kScreenW - 30, height: 30))
titleLabel.text = "这是一条测试富文本的字符串"
view.addSubview(titleLabel)
let attributeString = NSMutableAttributedString(string: "这是一条测试富文本的字符串")
//设置文本颜色,文本大小,背景颜色 也可以单独设置
attributeString.addAttributes([NSAttributedString.Key.foregroundColor: Global.color.RGBColor(0.2, 0.2, 0.2), NSAttributedString.Key.font: Global.font.regularFont14,NSAttributedString.Key.backgroundColor: Global.color.RGBColor(0.5, 0.3, 0.7)], range: NSRange(location: 0, length: 6))
//设置单个属性
//attributeString.addAttribute(NSAttributedString.Key, value: Any, range: NSRange)
//设置下划线
attributeString.addAttributes([NSAttributedString.Key.underlineStyle: 1, NSAttributedString.Key.underlineColor: Global.color.maincolor], range: NSRange(location: 6, length: 3))
//设置删除线
attributeString.addAttributes([NSAttributedString.Key.strikethroughStyle: 1, NSAttributedString.Key.strikethroughColor: Global.color.maincolor], range: NSRange(location: 9, length: 3))
titleLabel.attributedText = attributeString
let attributeString = NSMutableAttributedString(string: "这是测试UILabel行间距的text。这是测试UILabel行间距的text。\n这是测试UILabel行间距的text。\n这是测试UILabel行间距的text。这是测试UILabel行间距的text。这是测试UILabel行间距的text。这是测试UILabel行间距的text。")
let paraStyle = NSMutableParagraphStyle()
paraStyle.lineSpacing = 20.0
attributeString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paraStyle , range: NSRange(location: 0, length: attributeString.length))
titleLabel.attributedText = attributeString
关于NSAttributedString.Key 单独章节讲述
重要方法
- 计算UILabel随字体多行后的高度
func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect
示例代码:新建一个Label继承UILabel,并新增一个边距属性,并重写drawText方法
let titleLabel = UILabel(frame: CGRect(x: 15, y: 150, width: kScreenW - 30, height: 200))
titleLabel.numberOfLines = 0
view.addSubview(titleLabel)
titleLabel.text = "这是测试UILabel行间距的text。这是测试UILabel行间距的text。\n这是测试UILabel行间距的text。\n这是测试UILabel行间距的text。这是测试UILabel行间距的text。这是测试UILabel行间距的text。这是测试UILabel行间距的text。"
let rect = titleLabel.textRect(forBounds: titleLabel.bounds, limitedToNumberOfLines: 0)
var newRect = titleLabel.frame
newRect.size = rect.size
titleLabel.frame = newRect//更新UILabel的frame
- 设置内边距textInsets
func drawText(in rect: CGRect)
示例代码:
class ZQLabel: UILabel {
public var textInsets: UIEdgeInsets = .zero
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
internal init(frame: CGRect, textInsets: UIEdgeInsets) {
self.textInsets = textInsets
super.init(frame: frame)
}
override func drawText(in rect: CGRect) {
super.drawText(in: rect.inset(by: textInsets))
}
}
使用上面重写的Label:
let titleLabel = ZQLabel(frame: CGRect(x: 15, y: 150, width: kScreenW - 30, height: 200),textInsets: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))//添加边距
titleLabel.numberOfLines = 0
view.addSubview(titleLabel)
titleLabel.text = "这是测试UILabel行间距的text。这是测试UILabel行间距的text。\n这是测试UILabel行间距的text。\n这是测试UILabel行间距的text。这是测试UILabel行间距的text。这是测试UILabel行间距的text。这是测试UILabel行间距的text。"
let rect = titleLabel.textRect(forBounds: titleLabel.bounds.inset(by: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)), limitedToNumberOfLines: 0)//重新计算的时候也需要将边距考虑进去 也可以用作预留高度,不拥挤更美观
var newRect = titleLabel.frame
newRect.size = rect.size
titleLabel.frame = newRect
- 用于已知tag值的UILabel
//获取superView上指定tag值的UILabel
let getTagView = view.viewWithTag(100) as! UILabel
UITextFiled 文本输入框
初始化
UITextFiled继承自UIControl,遵守UITextInput,NSCoding,UIContentSizeCategoryAdjusting协议,没有特有初始化器
let textFiled = UITextField(frame: CGRect(x: 15, y: 100, width: kScreenW-30, height: 44))
重要实例属性
- borderStyle 边框 UITextField.BorderStyle default is none
- text 文本
- textColor 文本颜色 default is nil(black)
- textAlignment 对齐方式 default is NSLeftTextAlignment
- placeholder 占位符
- clearsOnBeginEditing 在开始编辑时清除 Bool
- adjustsFontSizeToFitWidth 默认为flase, 如果是,则文本将缩小到minFontSize
- minimumFontSize 最小文本尺寸
- background 要设置必须 borderStyle = .none
- disabledBackground 要生效必须 borderStyle = .none且isEnabled = false
- isEditing 只读属性 是否在编辑状态
- clearButtonMode 清除按钮(右侧叉叉)
- leftView 设置文本框左侧图片
- leftViewMode 设置文本框左侧图片显示模式
- rightView 设置文本框右侧图片 会影响清除按钮
- rightViewMode 设置文本框右侧图片显示模式
- delegate 代理 重要 default is nil. weak reference弱引用
- autocapitalizationType 为UITextInputTraits协议中的计算属性 自动大写的情况
- keyboardType 为UITextInputTraits协议中的计算属性 键盘类型
- isSecureTextEntry 为UITextInputTraits协议中的计算属性 安全输入
- inputView 在下层弹出view,并且没有键盘
- inputAccessoryView 推出一个键盘 并在键盘上方有view
- attributedPlaceholder 设置placeHolder富文本(可用于修改颜色、字体等)
富文本相关属性,不再讲述
attributedText、defaultTextAttributes、attributedPlaceholder、allowsEditingTextAttributes、typingAttributes·
类型属性
利用NotificationCenter消息通信机制观察UITextField的状态,UITextField本身自带三个消息类型:
class let textDidBeginEditingNotification: NSNotification.Name
class let textDidEndEditingNotification: NSNotification.Name
class let textDidChangeNotification: NSNotification.Name
代码示例:
在需要的地方注册通知,并实现选择器方法 在不需要的时候解除通知即可
//注册通知
NotificationCenter.default.addObserver(self, selector: #selector(tapAction), name: UITextField.textDidChangeNotification, object: nil)
//解除通知
kNotificationCenter.removeObserver(self, name: UITextField.textDidChangeNotification, object: nil)
重要方法(常用于自定义TextFiled)
func borderRect(forBounds bounds: CGRect) -> CGRect
func textRect(forBounds bounds: CGRect) -> CGRect
func placeholderRect(forBounds bounds: CGRect) -> CGRect
func editingRect(forBounds bounds: CGRect) -> CGRect
func clearButtonRect(forBounds bounds: CGRect) -> CGRect
func leftViewRect(forBounds bounds: CGRect) -> CGRect
func rightViewRect(forBounds bounds: CGRect) -> CGRect
func drawText(in rect: CGRect)
func drawPlaceholder(in rect: CGRect)
示例代码:
class ZQTextFiled: UITextField {
public var textInsets: UIEdgeInsets = .zero
public var clearButtonInsets: UIEdgeInsets = .zero
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
internal init(frame: CGRect, textInsets: UIEdgeInsets, clearButtonInsets: UIEdgeInsets) {
self.textInsets = textInsets
self.clearButtonInsets = clearButtonInsets
super.init(frame: frame)
}
//调整placeholder的位置
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
super.placeholderRect(forBounds: bounds.inset(by: textInsets))
}
//调整显示text的位置 结束编辑之后
override func textRect(forBounds bounds: CGRect) -> CGRect {
super.textRect(forBounds: bounds.inset(by: textInsets))
}
//调整编辑状态光标起始位置
override func editingRect(forBounds bounds: CGRect) -> CGRect {
super.editingRect(forBounds: bounds.inset(by: textInsets))
}
//调整清除按钮的位置
override func clearButtonRect(forBounds bounds: CGRect) -> CGRect {
super.clearButtonRect(forBounds: bounds.inset(by: clearButtonInsets))
}
//调整左侧view的位置
override func leftViewRect(forBounds bounds: CGRect) -> CGRect{
super.leftViewRect(forBounds: bounds.inset(by: textInsets))
}
//调整右侧view的位置
override func rightViewRect(forBounds bounds: CGRect) -> CGRect{
super.rightViewRect(forBounds: bounds.inset(by: clearButtonInsets))
}
}
UITextFiled代理
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool // return NO to disallow editing.
func textFieldDidBeginEditing(_ textField: UITextField) // became first responder
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool // return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end
func textFieldDidEndEditing(_ textField: UITextField) // may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) // if implemented, called in place of textFieldDidEndEditing:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool // return NO to not change text
func textFieldDidChangeSelection(_ textField: UITextField)
func textFieldShouldClear(_ textField: UITextField) -> Bool // called when clear button pressed. return NO to ignore (no notifications)
func textFieldShouldReturn(_ textField: UITextField) -> Bool // called when 'return' key pressed. return NO to ignore.
示例代码:
// 询问是否可以编辑 true 可以编辑 false 不能编辑
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
print("可以编辑")
return true
}
// 已经可以开始编辑 进入编辑状态
func textFieldDidBeginEditing(_ textField: UITextField) {
print("正在编辑状态中...")
}
// 将要将要结束编辑
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
print("即将编辑结束...")
return true
}
// 结束编辑状态
func textFieldDidEndEditing(_ textField: UITextField) {
print("已经结束编辑状态...")
}
// 文本框是否可以清除内容
func textFieldShouldClear(_ textField: UITextField) -> Bool {
return true
}
// 输入框按下键盘 return 收回键盘
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
// 该方法当文本框内容出现变化时 及时获取文本最新内容 控制输入格式
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
print("已经结束编辑状态...")
if string.count == 0 {
return true
}
let existedLength = textField.text?.count ?? 0
let selectedLength = range.length
let replaceLength = string.count
let currentString = (textField.text ?? "") + string
if currentString.count == 1 {
textField.text = "1"
return false
}
if existedLength - selectedLength + replaceLength > 11 {
return false;
}
return true
}
UITextFiled其余自定义设置
这里其实之前都讲述过,这里再提一下
- 光标颜色 tintColor 关于tintColor
- placeholder字体颜色等属性 attributedPlaceholder属性设置富文本即可
示例代码:
textFiled?.attributedPlaceholder = NSAttributedString(string: "请输入手机号", attributes: [NSAttributedString.Key.font : Global.font.regularFont(10), NSAttributedString.Key.foregroundColor : kRGBColor(1, 0, 0)])
UITextView
UITextView 继承自UIScrollView,遵守协议UITextInput(继承自UITextInputTraits), UIContentSizeCategoryAdjusting
初始化
//继承自UIView初始化器进行初始化
let textView = UITextView(frame: CGRect(x: 15, y: 150, width: kScreenW/2, height: 50))
//特有初始化器进行初始化
let container = NSTextContainer()
container.maximumNumberOfLines = 3
let textView = UITextView(frame: CGRect(x: 15, y: 150, width: kScreenW/2, height: 50), textContainer: container)
重要实例属性
- 继承自UIScrollView,相关属性在UIScrollView中讲述
- delegate 代理 重要 default is nil. weak reference弱引用
- text 显示文本
- font 文本字体
- textColor 文本颜色·
- attributedText 富文本 不再赘述
- textAlignment 对齐方式
- selectedRange 选中一段文本 可与becomeFirstResponder一起用,也可在textView代理中使用
- isEditable 是否可编辑
- isSelectable 是否可以点击 (isSelectable为false textView也无法编辑)
- dataDetectorTypes 识别类型,如电话号码 邮箱 地址 网址等
- inputView 在下层弹出view,并且没有键盘
- inputAccessoryView 推出一个键盘 并在键盘上方有view
- clearsOnInsertion 设置 UITextView 是否点击编辑时把旧内容全选
- textContainer 只读属性 textContainer常用于文本分页,电子书相关 在其他章节单独讲述
- textContainerInset 设置 UITextView 的文本容器边界
- typingAttributes 该字段存储了用于设置新输入的文本属性的键值对,比如字号,字体,颜色等。当光标的位置改变时,该值也会被清空再重置
- allowsEditingTextAttributes 在长按下是否可以选择不同的文字样式 实际使用效果不明
【注意】需要注意的几个属性:
textView.text = "13387564900范德萨2019-12-20发送到武汉市洪山区光谷国际广场吃的啥饭3045560657@qq.com,www.baidu.com"
//dataDetectorTypes只有在不可编辑状态下才能识别
textView.isEditable = true
textView.dataDetectorTypes = .all
//对于复制粘贴进入UITextView的文本,应该保证粘入文本的属性保持一致
//否则如果光标在 @XXX 这些不同于一般文本的位置上,在此处粘贴的内容就会和 @XXX一样,所以为了防止这一问题
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
textView.typingAttributes = self.textAttributes;
return YES;
}
重要类型属性
同TextFiled,不再赘述
UITextViewDelegate
继承自UIScrollViewDelegate,这里只讲述UITextViewDelegate特有的
//如果返回false,文本视图不能编辑
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool
//如果返回false,表示编辑结束之后,文本视图不可再编辑
func textViewShouldEndEditing(_ textView: UITextView) -> Bool
//开始编辑时候触发
func textViewDidBeginEditing(_ textView: UITextView)
//结束编辑时候触发
func textViewDidEndEditing(_ textView: UITextView)
//文本视图内容改变时,触发本方法 适合做数字和英文的输入限制
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool
//文本视图改变后触发本代理方法 适合做中文输入限制,以及placeholder
func textViewDidChange(_ textView: UITextView)
//文本视图 改变选择内容,触发本代理方法
//注意:手动调整光标位置时触发的委托,在第一次启动TextView编辑时,也会触发,会优先于键盘启动观察者事件,可以在这里区别是哪个TextView启动了键盘。本委托的优先执行率高于 textViewDidBeginEditing 代理 也高于 UIKeyboardWillShowNotification 通知
func textViewDidChangeSelection(_ textView: UITextView)
//链接在文本中显示。当链接被点击的时候,会触发本代理方法
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
//文本视图允许提供文本附件,文本附件点击时,会触发本代理方法 return true
func textView(_ textView: UITextView, shouldInteractWith textAttachment: NSTextAttachment, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
UISearchBar
UISearchBar 继承自UIView,遵守协议UIBarPositioning与UITextInputTraits
初始化
let searchBar = UISearchBar(frame: CGRect(x: 15, y: 150, width: kScreenW/2, height: 50))
此处设置frame的height需要注意:height仅为UISearchBar的高度,UISearchBarTextField的高度依然为36,若UISearchBar高度小于36,则显示不完全
UISearchTextField为UISearchBar的子类,也可以用作其他地方,系统通过UITextInput协议来驱动选择和键盘行为,并且UISearchTextField支持选择标记
重要实例属性
- delegate 代理 重要 default is nil. weak reference弱引用
- barStyle .default .black 两种情况,其余iOS13已失效
- text 搜索文本
- prompt //在UISearchTextFiled顶部居中文字做提示 需增加UISearchBar的Height
- placeholder 提示文字
- showsBookmarkButton 输入框内右侧显示书本按钮 default is NO
- showsCancelButton 输入框外右侧显示cancel按钮 default is NO
- showsSearchResultsButton 输入框内右侧显示向下箭头的按钮 default is NO
- isSearchResultsButtonSelected default is NO
- barTintColor 设置UISearchBar 背景色
- isTranslucent 设置半透明
- backgroundImage 设置背景图 填充方式有点特别
- searchTextField 继承自UITextFiled 需要修改相关textFiled属性(如提示文字字体颜色等)
- showsScopeBar 显示ScopeBar,设置ScopeBar通过方法设置
- scopeButtonTitles ScopeBar的按钮,[string]
- selectedScopeButtonIndex ScopeBar的选中下标
- searchFieldBackgroundPositionAdjustment 在搜索栏中微调搜索文本字段背景的位置
- searchTextPositionAdjustment 在搜索文本字段背景中微调文本的位置
barTintColor 设置UISearchBar 背景色
因为UISearchBar视图层级有些复杂,设置自身的backgroundColor会达不到想要的效果,会导致上下有两条线
重要实例方法
//替换UISearchBar左右侧的按钮 UISearchBar.Icon:.search .bookmark
//但是无法控制尺寸 也可通过searchTextField.leftView修改
func setImage(_ iconImage: UIImage?, for icon: UISearchBar.Icon, state: UIControl.State)
//获取当前图片
func image(for icon: UISearchBar.Icon, state: UIControl.State) -> UIImage?
//设置ScopeBar的背景图片 PS:但会影响选中状态
func setScopeBarButtonBackgroundImage(_ backgroundImage: UIImage?, for state: UIControl.State)
//ScopeBar的背景图片
func scopeBarButtonBackgroundImage(for state: UIControl.State) -> UIImage?
//设置ScopeBar按钮间分隔图 需要设置多次 eg:都未选中时,左边选中时,右边选中时 显示图片就会根据点击状态变化
func setScopeBarButtonDividerImage(_ dividerImage: UIImage?, forLeftSegmentState leftState: UIControl.State, rightSegmentState rightState: UIControl.State)
//获取某一状态时候ScopeBar按钮间分隔图
func scopeBarButtonDividerImage(forLeftSegmentState leftState: UIControl.State, rightSegmentState rightState: UIControl.State) -> UIImage?
//设置ScopeBar按钮的文字属性
func setScopeBarButtonTitleTextAttributes(_ attributes: [NSAttributedString.Key : Any]?, for state: UIControl.State)
//获取ScopeBar按钮的文字属性
func scopeBarButtonTitleTextAttributes(for state: UIControl.State) -> [NSAttributedString.Key : Any]?
//在搜索文本字段中微调图标的位置
func setPositionAdjustment(_ adjustment: UIOffset, for icon: UISearchBar.Icon)
//获取文本字段中图标的位置
func positionAdjustment(for icon: UISearchBar.Icon) -> UIOffset
UISearchBarDelegate
- 编辑代理
//文本更改(包括清除)时调用
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
//在文本即将更改时调用 控制输入格式
func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool
//设置false 无法输入 无法成为第一响应者 设置YES,即将开始时调动(询问)
func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool
//文本开始输入时调用
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar)
//返回false则无法结束输入 一般为true 设置YES,即将结束时调动(询问)
func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool
//文本结束输入时调用
func searchBarTextDidEndEditing(_ searchBar: UISearchBar)
- 按钮点击代理
//按下键盘搜索按钮时调用
func searchBarSearchButtonClicked(_ searchBar: UISearchBar)
//按下书本按钮时调用
func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar)
//按下cancel按钮时调用
func searchBarCancelButtonClicked(_ searchBar: UISearchBar)
//按下搜索结果按钮时调用
func searchBarResultsListButtonClicked(_ searchBar: UISearchBar)
//当ScopeButton的下标变化时调用
func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int)
本节相关属性,方法,代理实在太多,就不一一示例了
网友评论