Swift - UI

6、UILabel、UITextFiled、UITextView

2020-03-12  本文已影响0人  爱玩游戏的iOS菜鸟

本章主要讲述文本显示及输入相关控件UILabel、UITextFiled、UITextView、UISearchBar,其他相关的UISearchController、UISearchDisplayController以后再学习

UILabel标签

初始化

UILabel没有特有的初始化器,继承自UIView,用frame初始化

  let label = UILabel(frame: CGRect(x: 15, y: 200, width: 100, height: 20))
重要属性

继承自UIView,相关属性不再赘述

其中两个枚举 NSTextAlignmentNSLineBreakMode

  1. NSTextAlignment:
  1. NSLineBreakMode
富文本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 单独章节讲述

重要方法
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
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
  //获取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))
重要实例属性

富文本相关属性,不再讲述
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其余自定义设置

这里其实之前都讲述过,这里再提一下

  1. 光标颜色 tintColor 关于tintColor
  2. 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)
重要实例属性

【注意】需要注意的几个属性:

  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支持选择标记

重要实例属性

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
  1. 编辑代理
  //文本更改(包括清除)时调用
  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)
  1. 按钮点击代理
  //按下键盘搜索按钮时调用
  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)

本节相关属性,方法,代理实在太多,就不一一示例了

上一篇下一篇

猜你喜欢

热点阅读