UIScrollView 在键盘上向上滚动
UIScrollView scroll up on Keyboard
问题陈述:我有 UIView 的 Nib 文件包含 UIScrollview,在滚动视图中我有几个 TextFields 和一个位于底部的 TextView。我想要的是在 textfield 或 Textview 开始编辑时向上滚动。
我试过的:
在客户方法中
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
我正在调用此方法父视图。
通知处理:
func keyboardWasShown(notification: NSNotification)
{
var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
keyboardFrame = self.convert(keyboardFrame, from: nil)
var contentInset:UIEdgeInsets = self.mainScroll.contentInset
contentInset.bottom = keyboardFrame.size.height
self.mainScroll.contentInset = contentInset
}
这对 UITextFields 非常有效,但对 UITextView 无效。知道错误在哪里。
PS: 我也设置了UITextField和UITextView的Delegates
任何帮助将不胜感激。
用以下函数替换 keyboardWasShown 函数:
func keyboardWasShown(notification: NSNotification)
{
var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
keyboardFrame = self.convert(keyboardFrame, from: nil)
self.mainScroll.contentOffset = CGPoint(x: 0, y: keyboardFrame.size.height - Any number that fits your need.)
}
在 keyBoardWillHide 中:
self.mainScroll.contentOffset = CGPoint(x: 0, y: 0)
希望对您有所帮助。
快乐编码!
演示 link:https://github.com/harshilkotecha/UIScrollViewWhenKeyboardAppearInSwift3
当你有多个 textview 时,它是如此困难,所以最好的解决方案 ->
第 1 步:添加 UITextFieldDelegate
class ScrollViewController: UIViewController,UITextFieldDelegate {
第 2 步:创建新的 IBOutlet 但不连接任何文本字段
// get current text box when user Begin editing
@IBOutlet weak var activeTextField: UITextField?
第 3 步:当用户关注文本字段对象时编写这两个方法传递引用并存储在 activeTextField
// get current text field
func textFieldDidBeginEditing(_ textField: UITextField)
{
activeTextField=textField;
}
func textFieldDidEndEditing(_ textField: UITextField)
{
activeTextField=nil;
}
第 5 步:在 viewdidload 中设置通知 setNotificationKeyboard
override func viewWillAppear(_ animated: Bool) {
// call method for keyboard notification
self.setNotificationKeyboard()
}
// Notification when keyboard show
func setNotificationKeyboard () {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: .UIKeyboardWillHide, object: nil)
}
第 6 步:隐藏和显示键盘的两种方法
func keyboardWasShown(notification: NSNotification)
{
var info = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height+10, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeField = self.activeTextField
{
if (!aRect.contains(activeField.frame.origin))
{
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
// when keyboard hide reduce height of scroll view
func keyboardWillBeHidden(notification: NSNotification){
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0,0.0, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.endEditing(true)
}
Swift 5
NotificationCenter.default.addObserver(self, selector: #selector(keyboardNotification), name: UIResponder.keyboardDidChangeFrameNotification, object: nil)
@objc func keyboardNotification(_ notification: Notification) {
if let userInfo = (notification as NSNotification).userInfo {
let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let duration:TimeInterval = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions().rawValue
let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)
if (endFrame?.origin.y)! >= UIScreen.main.bounds.size.height {
scrollViewBottomConstraint?.constant = 0
} else {
if tabBarController?.tabBar.frame == nil {
return
}
scrollViewBottomConstraint?.constant = endFrame!.size.height - (tabBarController?.tabBar.frame.height)!
let bottomOffset = CGPoint(x: 0, y: 0)
scrollView.setContentOffset(bottomOffset, animated: true)
}
UIView.animate(withDuration: duration, delay: 0, options: animationCurve, animations: { self.view.layoutIfNeeded() }, completion: nil)
}
}
用法:
1.connect the scrollView outlet to your controller and set its name to 'scrollView'
2.connect the scrollView bottom constraint to your controller & set its name to 'scrollViewBottomConstraint'
3.put the notification observer to your ViewDidLoad function.
问题陈述:我有 UIView 的 Nib 文件包含 UIScrollview,在滚动视图中我有几个 TextFields 和一个位于底部的 TextView。我想要的是在 textfield 或 Textview 开始编辑时向上滚动。
我试过的:
在客户方法中
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
我正在调用此方法父视图。
通知处理:
func keyboardWasShown(notification: NSNotification)
{
var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
keyboardFrame = self.convert(keyboardFrame, from: nil)
var contentInset:UIEdgeInsets = self.mainScroll.contentInset
contentInset.bottom = keyboardFrame.size.height
self.mainScroll.contentInset = contentInset
}
这对 UITextFields 非常有效,但对 UITextView 无效。知道错误在哪里。
PS: 我也设置了UITextField和UITextView的Delegates
任何帮助将不胜感激。
用以下函数替换 keyboardWasShown 函数:
func keyboardWasShown(notification: NSNotification)
{
var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
keyboardFrame = self.convert(keyboardFrame, from: nil)
self.mainScroll.contentOffset = CGPoint(x: 0, y: keyboardFrame.size.height - Any number that fits your need.)
}
在 keyBoardWillHide 中:
self.mainScroll.contentOffset = CGPoint(x: 0, y: 0)
希望对您有所帮助。 快乐编码!
演示 link:https://github.com/harshilkotecha/UIScrollViewWhenKeyboardAppearInSwift3
当你有多个 textview 时,它是如此困难,所以最好的解决方案 ->
第 1 步:添加 UITextFieldDelegate
class ScrollViewController: UIViewController,UITextFieldDelegate {
第 2 步:创建新的 IBOutlet 但不连接任何文本字段
// get current text box when user Begin editing
@IBOutlet weak var activeTextField: UITextField?
第 3 步:当用户关注文本字段对象时编写这两个方法传递引用并存储在 activeTextField
// get current text field
func textFieldDidBeginEditing(_ textField: UITextField)
{
activeTextField=textField;
}
func textFieldDidEndEditing(_ textField: UITextField)
{
activeTextField=nil;
}
第 5 步:在 viewdidload 中设置通知 setNotificationKeyboard
override func viewWillAppear(_ animated: Bool) {
// call method for keyboard notification
self.setNotificationKeyboard()
}
// Notification when keyboard show
func setNotificationKeyboard () {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: .UIKeyboardWillHide, object: nil)
}
第 6 步:隐藏和显示键盘的两种方法
func keyboardWasShown(notification: NSNotification)
{
var info = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height+10, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeField = self.activeTextField
{
if (!aRect.contains(activeField.frame.origin))
{
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
// when keyboard hide reduce height of scroll view
func keyboardWillBeHidden(notification: NSNotification){
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0,0.0, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.endEditing(true)
}
Swift 5
NotificationCenter.default.addObserver(self, selector: #selector(keyboardNotification), name: UIResponder.keyboardDidChangeFrameNotification, object: nil)
@objc func keyboardNotification(_ notification: Notification) {
if let userInfo = (notification as NSNotification).userInfo {
let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let duration:TimeInterval = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions().rawValue
let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)
if (endFrame?.origin.y)! >= UIScreen.main.bounds.size.height {
scrollViewBottomConstraint?.constant = 0
} else {
if tabBarController?.tabBar.frame == nil {
return
}
scrollViewBottomConstraint?.constant = endFrame!.size.height - (tabBarController?.tabBar.frame.height)!
let bottomOffset = CGPoint(x: 0, y: 0)
scrollView.setContentOffset(bottomOffset, animated: true)
}
UIView.animate(withDuration: duration, delay: 0, options: animationCurve, animations: { self.view.layoutIfNeeded() }, completion: nil)
}
}
用法:
1.connect the scrollView outlet to your controller and set its name to 'scrollView'
2.connect the scrollView bottom constraint to your controller & set its name to 'scrollViewBottomConstraint'
3.put the notification observer to your ViewDidLoad function.