就像我在这个答案中提到的那样:
我已经根据自己的需要开发了一个框架来更好地解决这个问题,并现在将其公开。它不仅适用于 UITextField 和 UITextView,它适用于任何采用 UITextInput 协议的自定义 UIView,如 UITextField 和 UITextView,并提供许多有用的功能。你可以通过 Carthage、CocoaPods 或 Swift Package Manager 安装它。
ODScrollView GitHub
ODScrollView 中
ODScrollView 只是一个 UIScrollView,它可以根据键盘可见性自动垂直移动 UITextField 和 UITextView 等可编辑文本区域,以提供更好的用户体验。
特征
- 当键盘出现/消失时,自动向上/向下移动采用 UITextInput 协议的第一响应者 UIView,例如 UITextField、UITextView、UISearchTextField 或任何采用 UITextInput 协议的自定义 UIView。
- 请注意,如果 UITextInput 的框架不适合 ODScrollView 和键盘之间的剩余区域,则 ODScrollView 会根据光标位置而不是框架调整 UITextInput。在这种情况下,可以使用“trackTextInputCursor”功能。例子
可以为每个 UITextInput 单独应用调整边距,用于 .Top 和 .Bottom 调整方向设置。默认为 20 CGFloat。
可以单独为每个 UITextInput 启用/禁用调整。默认情况下为真。
调整方向 - .Top、.Center、.Bottom - 可以分别应用于每个 UITextInput。.底部默认。例子
- 调整选项决定了 ODScrollView 如何调整。.始终默认。
- .Always :ODScrollView 始终调整放置在 ODScrollView 中任何位置的 UITextInput,无论 UITextInput 是否与显示的键盘重叠。例子
- .IfNeeded :ODScrollView 仅在 UITextInput 与显示的键盘重叠时才调整它。例子
- 除了 UIScrollView.keyboardDismissModes 之外,还可以通过点击 ODScrollViewDelegate 提供的 UIView 来关闭键盘。键盘关闭后,ODScrollView 可以返回原来的位置。默认情况下为 nil 和 false。例子
用法
1 -您需要做的第一件事是正确设置 ODScrollView 及其内容视图。由于 ODScrollView 只是一个 UIScrollView,因此您可以以与 UIScrollView 相同的方式实现 ODScrollView。您可以使用情节提要或以编程方式创建 ODScrollView。
如果您以编程方式创建 ODScrollView,则可以从步骤 4 继续。
在 Storyboard 中创建 UIScrollView 的建议方法
- If you are using Content Layout Guide and Frame Layout Guide:
1.1 - scrollView: Place UIScrollView anywhere you want to use.
1.2 - contentView: Place UIView inside scrollView.
1.3 - Set contentView's top, bottom, leading and trailing constraints to Content Layout Guide's constraints.
1.4 - Set contentView's width equal to Frame Layout Guide's width.
1.5 - Set contentView's height equal to Frame Layout Guide's height or set static height which is larger than scrollView's height.
1.6 - Build your UI inside contentView.
- If you are NOT using Content Layout Guide and Frame Layout Guide:
1.1 - scrollView: Place UIScrollView anywhere you want to use.
1.2 - contentView: Place UIView inside scrollView.
1.3 - Set contentView's top, bottom, leading and trailing constraints to 0.
1.4 - Set contentView's width equal to scrollView's width.
1.5 - Set contentView's height equal to scrollView's superview's height or set static height which is larger than scrollView's height.
1.6 - Build your UI inside contentView.
2 -在 Storyboard 的身份检查器中将滚动视图的类从 UIScrollView 更改为 ODScrollView。
3 -在 ViewController 上为 scrollView 和 contentView 创建 IBOutlets。
4 -在 ViewController 上的 ViewDidLoad() 中调用以下方法:
override func viewDidLoad() {
super.viewDidLoad()
//ODScrollView setup
scrollView.registerContentView(contentView)
scrollView.odScrollViewDelegate = self
}
5 -可选:您仍然可以使用 UIScrollView 的功能:
override func viewDidLoad() {
super.viewDidLoad()
//ODScrollView setup
scrollView.registerContentView(contentView)
scrollView.odScrollViewDelegate = self
// UIScrollView setup
scrollView.delegate = self // UIScrollView Delegate
scrollView.keyboardDismissMode = .onDrag // UIScrollView keyboardDismissMode. Default is .none.
UITextView_inside_contentView.delegate = self
}
6 -采用 ViewController 中的 ODScrollViewDelegate 并决定 ODScrollView 选项:
extension ViewController: ODScrollViewDelegate {
// MARK:- State Notifiers: are responsible for notifiying ViewController about what is going on while adjusting. You don't have to do anything if you don't need them.
// #Optional
// Notifies when the keyboard showed.
func keyboardDidShow(by scrollView: ODScrollView) {}
// #Optional
// Notifies before the UIScrollView adjustment.
func scrollAdjustmentWillBegin(by scrollView: ODScrollView) {}
// #Optional
// Notifies after the UIScrollView adjustment.
func scrollAdjustmentDidEnd(by scrollView: ODScrollView) {}
// #Optional
// Notifies when the keyboard hid.
func keyboardDidHide(by scrollView: ODScrollView) {}
// MARK:- Adjustment Settings
// #Optional
// Specifies the margin between UITextInput and ODScrollView's top or bottom constraint depending on AdjustmentDirection
func adjustmentMargin(for textInput: UITextInput, inside scrollView: ODScrollView) -> CGFloat {
if let textField = textInput as? UITextField, textField == self.UITextField_inside_contentView {
return 20
} else {
return 40
}
}
// #Optional
// Specifies that whether adjustment is enabled or not for each UITextInput seperately.
func adjustmentEnabled(for textInput: UITextInput, inside scrollView: ODScrollView) -> Bool {
if let textField = textInput as? UITextField, textField == self.UITextField_inside_contentView {
return true
} else {
return false
}
}
// Specifies adjustment direction for each UITextInput. It means that some of UITextInputs inside ODScrollView can be adjusted to the bottom, while others can be adjusted to center or top.
func adjustmentDirection(selected textInput: UITextInput, inside scrollView: ODScrollView) -> AdjustmentDirection {
if let textField = textInput as? UITextField, textField == self.UITextField_inside_contentView {
return .bottom
} else {
return .center
}
}
/**
- Always : ODScrollView always adjusts the UITextInput which is placed anywhere in the ODScrollView.
- IfNeeded : ODScrollView only adjusts the UITextInput if it overlaps with the shown keyboard.
*/
func adjustmentOption(for scrollView: ODScrollView) -> AdjustmentOption {
.Always
}
// MARK: - Hiding Keyboard Settings
/**
#Optional
Provides a view for tap gesture that hides keyboard.
By default, keyboard can be dismissed by keyboardDismissMode of UIScrollView.
keyboardDismissMode = .none
keyboardDismissMode = .onDrag
keyboardDismissMode = .interactive
Beside above settings:
- Returning UIView from this, lets you to hide the keyboard by tapping the UIView you provide, and also be able to use isResettingAdjustmentEnabled(for scrollView: ODScrollView) setting.
- If you return nil instead of UIView object, It means that hiding the keyboard by tapping is disabled.
*/
func hideKeyboardByTappingToView(for scrollView: ODScrollView) -> UIView? {
self.view
}
/**
#Optional
Resets the scroll view offset - which is adjusted before - to beginning its position after keyboard hid by tapping to the provided UIView via hideKeyboardByTappingToView.
## IMPORTANT:
This feature requires a UIView that is provided by hideKeyboardByTappingToView().
*/
func isResettingAdjustmentEnabled(for scrollView: ODScrollView) -> Bool {
true
}
}
7 -可选:在输入多行 UITextInput 时,当光标与键盘重叠时,您可以调整 ODScrollView。trackTextInputCursor(for UITextInput) 必须由键入时触发的 UITextInput 函数调用。
/**
## IMPORTANT:
This feature is not going to work unless textView is subView of _ODScrollView
*/
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
_ODScrollView.trackTextInputCursor(for textView)
return true
}