UITxtView跟随KeyBoard弹起收回

iOS开发中,经常需求点击输入框后,键盘弹起,而输入框也会出现在键盘上方,以UITxtView为例来实现。

目录:


效果展示#

键盘弹起后,自定义的输入框会出现在键盘上方,和键盘相吸。因为通常还有输入框高度自适应内容的需求,所以以UITxtView来处理这个问题的情况居多。

所以以评论框为例展示开发过程。

开发过程#

创建单例#

因为弹起状态的评论框通常是单个出现的,所以为了方便使用,我们可以设置成单例。

1
2
3
4
5
6
7
8
9
10
11
12
13
class CommentManager: NSObject {

// 创建单例
static let shared: CommentManager = {
let manager = CommentManager()
return manager
}()

// 私有化 init()
private override init() {
super.init()
}
}

设置子视图#

通常我们会包含两个子视图:

  1. 可点击的淡灰色背景
  2. 可输入内容的输入框

所以我们先创建好两个子视图:

1
2
3
4
5
6
7
8
9
10
11
12
13
var backgroudView: UIView = {
let view = UIView(frame: UIScreen.main.bounds)
view.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
return view
}()

var textView: UITextView = {
let view = UITextView(frame: CGRect(x: 0, y: DefineConst.HScreen, width: DefineConst.WScreen, height: 100))
view.backgroundColor = .white
view.layer.borderColor = UIColor.lightGray.cgColor
view.layer.borderWidth = 2
return view
}()

配置视图#

在初始化中,我们配置好子视图所需要的相关设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

private override init() {
super.init()
// 在初始化中配置
configView()
}

deinit {
// 取消通知
NotificationCenter.default.removeObserver(self)
}

private func configView() {
// textView设置delegate,并且添加到backgroudView上面
textView.delegate = self
backgroudView.addSubview(textView)

// backgroudView添加点击手势
backgroudView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(backGroudTaphander)))

// 添加键盘通知
NotificationCenter.default.addObserver(self, selector: #selector(keyboardFameChangeHander(notif:)), name: UIResponder.keyboardWillShowNotification, object: nil)
}

处理相关事件#

主要是处理背景点击事件 和 键盘的通知事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 背景点击,取消焦点,并且删除backgroudView
@objc private func backGroudTaphander() {
textView.resignFirstResponder()
backgroudView.removeFromSuperview()
}

@objc private func keyboardFameChangeHander(notif: Notification) {

// 获取通知的 键盘弹出时间,和键盘Fram
let duration = notif.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as! Float
let keyFrame = notif.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect

// 键盘弹出时提供一个textView的弹出动画
if keyFrame.origin.y >= backgroudView.bounds.height {

UIView.animate(withDuration: TimeInterval(duration)) {
self.textView.frame = CGRect(x: 0, y: DefineConst.HScreen, width: DefineConst.WScreen, height: 100)
}
}
else {
// 键盘不是弹出时,提供一个textView的回缩动画
textView.frame = CGRect(x: 0, y: DefineConst.HScreen, width: DefineConst.WScreen, height: 100)
let curKeyboardFrameH = DefineConst.HScreen - keyFrame.size.height - textView.bounds.height
UIView.animate(withDuration: TimeInterval(duration)) {
self.textView.frame = CGRect(x: 0, y: curKeyboardFrameH, width: DefineConst.WScreen, height: 100)
}
}
}

开放接口#

对外提供一个调用接口,方便直接使用。

1
2
3
4
5
6
7
8
9
public func showCommentInputView() {

// 将backgroudView添加到keywindow上面
let window = DefineConst.KeyWindow
window?.addSubview(backgroudView)

// textView获取焦点
textView.becomeFirstResponder()
}
iOS-组件化 iOS-剖析UIView

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×