ios 键盘显示时的 Tableview 滚动内容
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24529373/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Tableview scroll content when keyboard shows
提问by Andorath
I have a table view with a text field and a textview. I've implemented this code like suggested by this apple sample code https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
我有一个带有文本字段和文本视图的表视图。我已经实现了这个代码,就像这个苹果示例代码https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
@IBOutlet var myTableView: UITableView
func keyboardWasShown (notification: NSNotification)
{
println("keyboard was shown")
var info = notification.userInfo
var keyboardSize = info.objectForKey(UIKeyboardFrameBeginUserInfoKey).CGRectValue().size
myTableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
myTableView.scrollIndicatorInsets = myTableView.contentInset
}
func keyboardWillBeHidden (notification: NSNotification)
{
println("keyboard will be hidden")
myTableView.contentInset = UIEdgeInsetsZero
myTableView.scrollIndicatorInsets = UIEdgeInsetsZero
}
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}
When i click on the "text" of the scroll view go just above the top of the screen, but when i release the keyboard it remains scrolled up. It's just like the insets property can't be modified after the first time. What's my mistake?
当我单击滚动视图的“文本”时,它位于屏幕顶部的正上方,但是当我松开键盘时,它仍然向上滚动。就像第一次之后不能修改 insets 属性一样。我的错误是什么?
采纳答案by Yatheesha B L
Try keeping the editing index path editingIndexPathGetting index pathand scroll tableview to that index path
尝试保持编辑索引路径editingIndexPath获取索引路径并将tableview滚动到该索引路径
func keyboardWasShown (notification: NSNotification)
{
println("keyboard was shown")
var info = notification.userInfo
var keyboardSize = info.objectForKey(UIKeyboardFrameBeginUserInfoKey).CGRectValue().size
var contentInsets:UIEdgeInsets
if UIInterfaceOrientationIsPortrait(UIApplication.sharedApplication().statusBarOrientation) {
contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);
}
else {
contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.width, 0.0);
}
myTableView.contentInset = contentInsets
myTableView.scrollToRowAtIndexPath(editingIndexPath, atScrollPosition: .Top, animated: true)
myTableView.scrollIndicatorInsets = myTableView.contentInset
}
回答by Zany
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWillShow(_ notification:Notification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
}
}
func keyboardWillHide(_ notification:Notification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
}
}
回答by Soumen
Use this Awesome Extension (Updated for Swift 4.2),
使用这个很棒的扩展(针对 Swift 4.2 更新),
extension UIViewController {
func registerForKeyboardWillShowNotification(_ scrollView: UIScrollView, usingBlock block: ((CGSize?) -> Void)? = nil) {
_ = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil, using: { notification -> Void in
let userInfo = notification.userInfo!
let keyboardSize = (userInfo[UIResponder.keyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue.size
let contentInsets = UIEdgeInsets(top: scrollView.contentInset.top, left: scrollView.contentInset.left, bottom: keyboardSize.height, right: scrollView.contentInset.right)
scrollView.setContentInsetAndScrollIndicatorInsets(contentInsets)
block?(keyboardSize)
})
}
func registerForKeyboardWillHideNotification(_ scrollView: UIScrollView, usingBlock block: ((CGSize?) -> Void)? = nil) {
_ = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: nil, using: { notification -> Void in
let userInfo = notification.userInfo!
let keyboardSize = (userInfo[UIResponder.keyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue.size
let contentInsets = UIEdgeInsets(top: scrollView.contentInset.top, left: scrollView.contentInset.left, bottom: 0, right: scrollView.contentInset.right)
scrollView.setContentInsetAndScrollIndicatorInsets(contentInsets)
block?(keyboardSize)
})
}
}
extension UIScrollView {
func setContentInsetAndScrollIndicatorInsets(_ edgeInsets: UIEdgeInsets) {
self.contentInset = edgeInsets
self.scrollIndicatorInsets = edgeInsets
}
}
and use as mentioned below from the respective ViewController,
并从相应的 ViewController 中使用如下所述,
@IBOutlet weak var tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
registerForKeyboardWillShowNotification(tableview)
registerForKeyboardWillHideNotification(tableview)
/* use the above functions with
block, in case you want the trigger just after the keyboard
hide or show which will return you the keyboard size also.
*/
registerForKeyboardWillShowNotification(tableView) { (keyboardSize) in
print("size 1 - \(keyboardSize!)")
}
registerForKeyboardWillHideNotification(tableView) { (keyboardSize) in
print("size 2 - \(keyboardSize!)")
}
}
回答by Vitalik Kizlov
For Swift 4.2
对于 Swift 4.2
In viewDidLoad() of your UIViewController:
在 UIViewController 的 viewDidLoad() 中:
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
And implementation of selectors:
和选择器的实现:
@objc private func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
}
}
@objc private func keyboardWillHide(notification: NSNotification) {
tableView.contentInset = .zero
}
回答by Hardik Thakkar
Use below code to get Indexpath and change UITableview content Offset based on UIKeyboard Height
使用以下代码获取索引路径并根据 UIKeyboard 高度更改 UITableview 内容偏移
func keyboardWillShow(notification: NSNotification) {
if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
//self.view.frame.origin.y -= keyboardSize.height
var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
keyboardFrame = self.view.convert(keyboardFrame, from: nil)
var contentInset:UIEdgeInsets = self.tbl.contentInset
contentInset.bottom = keyboardFrame.size.height
self.tbl.contentInset = contentInset
//get indexpath
let indexpath = NSIndexPath(forRow: 1, inSection: 0)
self.tbl.scrollToRowAtIndexPath(indexpath, atScrollPosition: UITableViewScrollPosition.Top, animated: true)
}
}
func keyboardWillHide(notification: NSNotification) {
if ((notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
self.tbl.contentInset = contentInset
}
}
回答by Furkan Vijapura
** not scrolling to an upside on keyboard show**
** 不滚动到键盘显示的上行**
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWillShow(_ notification:Notification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
}
}
func keyboardWillHide(_ notification:Notification)
{
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
}
}
回答by DisplayName
You can also use textfield/textViewDidBeginEditing. I've used this for a chat log tableView.
您还可以使用 textfield/textViewDidBeginEditing。我已经将它用于聊天记录 tableView。
func textViewDidBeginEditing(_ textView: UITextView) {
if self.chatMessages.count >= 1 {
let section = self.chatMessages.count - 1
let row = self.chatMessages[section].count - 1
let indexPath = IndexPath(row: row, section: section )
self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
}
}
回答by Myrenkar
The easiest way is to simply set
最简单的方法是简单地设置
tableView.keyboardDismissMode = .onDrag
This will work out of the box.
这将是开箱即用的。
回答by patel dhruval
For Swift 5.0 and considering iPhone Predictive Text is On
对于 Swift 5.0 并考虑启用 iPhone 预测文本
take "keyboardSize.height + tableView.rowHeight" as the bottom of tableview just in case if iPhone Predictive Text is On. In that case, we need to scroll up tableview little more.
以“keyboardSize.height + tableView.rowHeight”作为tableview的底部,以防万一,如果iPhone Predictive Text开启。在这种情况下,我们需要再向上滚动 tableview。
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc private func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height + tableView.rowHeight, right: 0)
}
}
@objc private func keyboardWillHide(notification: NSNotification) {
tableView.contentInset = .zero
}
回答by chronikum
I had a small idea about that and I wrote an extension in swift. Feel free to contribute and use it in your own projects:
我对此有一个小想法,我用 swift 编写了一个扩展。随意贡献并在您自己的项目中使用它:
https://github.com/joluc/AutoAdjust
https://github.com/joluc/AutoAdjust
import Foundation
import UIKit
extension UITableView {
// I am working on a way to deinit the observers when the tableview also is deiniting.
// If you have ideas, feel free to help out!
func setupAutoAdjust()
{
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardshown), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardhide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
@objc func keyboardshown(_ notification:Notification)
{
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
self.fitContentInset(inset: UIEdgeInsetsMake(0, 0, keyboardSize.height, 0))
}
}
@objc func keyboardhide(_ notification:Notification)
{
if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
self.fitContentInset(inset: .zero)
}
}
func fitContentInset(inset:UIEdgeInsets!)
{
self.contentInset = inset
self.scrollIndicatorInsets = inset
}
}