iOS UITextView和UITextViewDelegate
在本教程中,我们将讨论UITextView元素,并在我们的应用程序中实现它的各种形式。
iOS UITextView
与它的名称不同,UITextView不仅仅是文本视图。
您可以对其进行编辑,键入,滚动。
UITextView是多行文本区域。
它具有内置的UIScrollView。
默认情况下,UITextView是可编辑的。
要禁用编辑,您需要将属性" isEditable"设置为" false"。
要以编程方式创建它,您需要创建一个指定宽度和高度的矩形:
let uiTextView = UITextView() uiTextView.frame = CGRect(x: 0, y: 0, width: 200, height: 150)
UITextView与UITextField UITextView用于多行输入,而UITextField默认情况下仅用于单行。
默认情况下,UITextView不提供占位符/提示文本。
UITextViewDelegate
UITextViewDelegate协议定义了一组可选方法,这些方法在编辑文本时触发。
所有协议方法都是可选的。
以下是UITextViewDelegate中提供的一些方法。
textViewDidBeginEditing/textViewWillBeginEditingtextViewDidEndEditing/textViewWillEndEditingtextViewDidChange-在编辑文本时被调用。textView(_ textView:UITextView,shouldChangeTextIn范围:NSRange,replaceText text:String)
–返回一个布尔值,询问是否应替换文本。
一个有趣的用例是在UITextView上设置字符限制:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText newText: String) -> Bool { return textView.text.count + (newText.count - range.length) <= 140 }
这将字符数限制设置为140。
就像Twitter!
UITextView的实现
创建一个新的XCode项目,开始吧:
在Main.storyboard中,将UITextView拖到ViewController上,并执行以下说明:
在UITextView上设置自动布局约束。
我们将其设置为固定高度的屏幕底部。通过助手编辑器使用IBOutlet将UITextView链接到ViewController.swift文件。
.
在模拟器和设备上运行应用程序后,我们得到:
那真是怪了!
键盘弹出UITextView上方。
单击返回时,键盘将关闭。
我们需要解决这些问题。
在您的ViewController.swift文件中添加以下代码:
import UIKit class ViewController: UIViewController, UITextViewDelegate { @IBOutlet weak var bottomTextView: UITextView! override func viewDidLoad() { super.viewDidLoad() bottomTextView.delegate = self NotificationCenter.default.addObserver(self, selector: #selector(ViewController.updateTextView(notification:)), name: Notification.Name.UIKeyboardWillChangeFrame, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(ViewController.updateTextView(notification:)), name: Notification.Name.UIKeyboardWillHide, object: nil) } func textViewDidBeginEditing(_ textView: UITextView) { textView.backgroundColor = UIColor.lightGray } func textViewDidEndEditing(_ textView: UITextView) { textView.backgroundColor = UIColor.white } func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { if text == "\n" { textView.resignFirstResponder() return false } return true } @objc func updateTextView(notification: Notification) { if let userInfo = notification.userInfo { let keyboardFrameScreenCoordinates = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue let keyboardFrame = self.view.convert(keyboardFrameScreenCoordinates, to: view.window) if notification.name == Notification.Name.UIKeyboardWillHide{ view.frame.origin.y = 0 } else{ view.frame.origin.y = -keyboardFrame.height } } } }
在上面的代码中,我们实现了UITextViewDelegate协议,实现了键盘关闭逻辑,并将UITextView移到了键盘上方。
- 要在UITextView上进行设置,我们要做:
bottomTextView.delegate = self
- 我们已经实现了UITextViewDelegate的三个功能-" textViewDidBeginEditing"," textViewDidEndEditing"和" textView(shouldChangeTextIn :)"。
在编辑开始和结束时,我们更改UITextView的背景颜色。
resignFirstResponder()用于关闭键盘。
为此,我们在UITextView上执行以下操作:
在viewDidLoad中,我们添加了两个Notification观察器,它们可检测Keyboard中的更改并触发函数" updateTextView"。
在" updateTextView"内部,我们根据通知名称更改UITextView的位置。
为了将UITextView移动到键盘上方,我们以编程方式计算键盘的高度,然后将整个视图向上移动该高度。
现在运行应用程序时的输出为:
接下来,我们将研究自动调整UITextViews的大小
自动调整大小的UITextView
UITextViews的大小可以根据其内容大小进行更改。
让我们在情节提要中创建另一个ViewController并通过Button segue将其连接。
将Button添加到当前的ViewController并设置约束。
创建另一个ViewController场景,然后使用Ctrl +单击以拖动按钮来创建序列。
创建一个新的Swift File SecondViewController.swift并在右窗格中设置名称
在SecondViewController.swift中,我们将以编程方式添加UITextView并通过Swift代码设置约束。
在下面的代码中,我们已经:
在UITextView上添加了占位符
键入更多内容时,会自动增加UITextView的高度。
在UITextView上设置字体大小
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { if text == "\n" { textView.resignFirstResponder() return false } return true }
textViewDidChange是UITextViewDelegate协议的一部分。
每当添加文本时,都会触发该事件。
每次我们计算文本的大小并增加UITextView的高度限制。
实际应用程序的输出为:
如您所见,UITextView的高度增加了。
但是,UITextView一直保持着上面的顶行。
这是由于ScrollBars。
我们可以通过在addAnotherTextView()函数中添加以下行来禁用它们:
import UIKit class SecondViewController: UIViewController, UITextViewDelegate { let topTextView = UITextView() override func viewDidLoad() { super.viewDidLoad() addAnotherTextView() } func addAnotherTextView() { topTextView.delegate = self topTextView.text = "Enter your notes here" topTextView.frame = CGRect(x: 0, y: 0, width: 200, height: 150) topTextView.font = .systemFont(ofSize: 20) view.addSubview(topTextView) topTextView.translatesAutoresizingMaskIntoConstraints = false [ topTextView.topAnchor.constraint(equalTo: view!.safeAreaLayoutGuide.topAnchor), topTextView.leadingAnchor.constraint(equalTo: view!.leadingAnchor), topTextView.trailingAnchor.constraint(equalTo: view!.trailingAnchor), topTextView.heightAnchor.constraint(equalToConstant: 40) ].forEach{ ``` sh topTextView.isScrollEnabled = false ```.isActive = true } } func textViewDidBeginEditing(_ textView: UITextView) { textView.backgroundColor = UIColor.lightGray if (textView.text == "Enter your notes here") { textView.text = "" textView.textColor = .black } } func textViewDidEndEditing(_ textView: UITextView) { textView.backgroundColor = UIColor.white if (textView.text == "") { textView.text = "Enter your notes here" textView.textColor = .lightGray } } func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { if text == "\n" { textView.resignFirstResponder() return false } return true } func textViewDidChange(_ textView: UITextView) { let size = CGSize(width: view.frame.width, height: .infinity) let approxSize = textView.sizeThatFits(size) textView.constraints.forEach{(constraint) in if constraint.firstAttribute == .height { constraint.constant = approxSize.height } } } }
现在,第一行并不会一直超出屏幕范围。
我们来看另一个用例。
自动调整UITextView的大小直到特定高度
我们可以调整UITextView的大小,使其只能扩展到特定的高度。
将您的textViewDidChange函数更改为:
func textViewDidChange(_ textView: UITextView) { if topTextView.contentSize.height >= 120.0 { topTextView.isScrollEnabled = true } else { let size = CGSize(width: view.frame.width, height: .infinity) let approxSize = textView.sizeThatFits(size) textView.constraints.forEach {(constraint) in if constraint.firstAttribute == .height{ constraint.constant = approxSize.height } } topTextView.isScrollEnabled = false } }
逻辑很简单:
每次增加高度时,请先检查是否达到最大高度。
如果是这样,就不再增加高度,只需启用滚动即可。
如果未达到最大高度,请禁用滚动条。