我有一个应用,它在视图的下半部分有一个文本框。 这意味着当我在文本框中输入时,键盘会覆盖文本框。
我如何在打字时向上移动视图,这样我就可以看到我键入的内容,然后在键盘消失时将它移回原来的位置?
我到处都看了,但所有的解似乎都在Obj-C中,我还不能完全转换。
任何帮助都将不胜感激。
我有一个应用,它在视图的下半部分有一个文本框。 这意味着当我在文本框中输入时,键盘会覆盖文本框。
我如何在打字时向上移动视图,这样我就可以看到我键入的内容,然后在键盘消失时将它移回原来的位置?
我到处都看了,但所有的解似乎都在Obj-C中,我还不能完全转换。
任何帮助都将不胜感激。
当前回答
这个实现(Swift 4)将给你的行为最接近Android的默认行为。Ie:当活动文本域在键盘下时,将视图向上移动,当用户切换到另一个视图时,无需关闭键盘。记住调用settextfielddelegate()。
public class DelegateProxy: NSObject, UITextFieldDelegate {
private static let instance = DelegateProxies()
weak var activeTextField: UITextField?
var offset: CGFloat = 0
weak var vc: UIViewController?
var keyboardHeight: CGFloat = 0
public static func getDelegate(root: UIViewController) -> DelegateProxies {
instance.vc = root
return instance
}
public static func getDelegate() -> DelegateProxies {
return instance
}
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.activeTextField = textField
let globalPointY: CGFloat = (textField.superview?.convert(textField.frame.origin, to: nil).y ?? CGFloat(0)) + textField.frame.height
offset = UIScreen.main.bounds.height - globalPointY
if keyboardHeight > 0 {
vc?.moveViewUp(offsetFromKeyboard: keyboardHeight - offset)
}
return true
}
}
extension UIViewController {
private func setTextFieldDelegates(parentView: UIView) {
for child in parentView.subviews {
setTextFieldDelegates(parentView: child)
(child as? UITextField)?.delegate = DelegateProxies.getDelegate(root: self)
}
}
func registerAutoResizeOnKeyboardAppear(){
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func unregisterAutoResizeOnKeyboard(){
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
let offsetFromKeyboard = keyboardSize.height - DelegateProxies.getDelegate().offset
DelegateProxies.getDelegate().keyboardHeight = keyboardSize.height
moveViewUp(offsetFromKeyboard: offsetFromKeyboard)
}
}
func moveViewUp(offsetFromKeyboard: CGFloat){
print("offset from keyboard: \(offsetFromKeyboard)")
let moveOffset = offsetFromKeyboard + 8
if offsetFromKeyboard > 0 {
self.view.frame.origin.y = -moveOffset
}
if offsetFromKeyboard < 0 && view.frame.origin.y < 0 {
self.view.frame.origin.y += -moveOffset
if self.view.frame.origin.y > 0{
self.view.frame.origin.y = 0
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
self.view.frame.origin.y = 0
}
}
其他回答
对我有用
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
var isScroll = false
@objc func keyboardWillShow(sender: NSNotification) {
if( !isScroll ){
self.view.frame.origin.y -= 150
isScroll = true
}
}
@objc func keyboardWillHide(sender: NSNotification) {
if( isScroll ){
self.view.frame.origin.y += 150
isScroll = false
}
}
这是我的解决方案(实际上这段代码是在你的视图中有几个文本字段的情况下,这也适用于当你有一个文本字段的情况下)
class MyViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var firstTextField: UITextField!
@IBOutlet weak var secondTextField: UITextField!
var activeTextField: UITextField!
var viewWasMoved: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
}
override func viewDidDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func textFieldDidBeginEditing(textField: UITextField) {
self.activeTextField = textField
}
func textFieldDidEndEditing(textField: UITextField) {
self.activeTextField = nil
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func keyboardWillShow(notification: NSNotification) {
let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
var aRect: CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
let activeTextFieldRect: CGRect? = activeTextField?.frame
let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.origin
if (!CGRectContainsPoint(aRect, activeTextFieldOrigin!)) {
self.viewWasMoved = true
self.view.frame.origin.y -= keyboardSize!.height
} else {
self.viewWasMoved = false
}
}
func keyboardWillHide(notification: NSNotification) {
if (self.viewWasMoved) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.origin.y += keyboardSize.height
}
}
}
Swift 4中的Simpelst方法
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var myTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
myTextField.resignFirstResponder()
}
func keyboardWillShow(notification: NSNotification) {
// let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]
// print("duration",duration)
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight : Int = Int(keyboardSize.height)
print("keyboardWillShow",keyboardHeight)
if let height = UserDefaults.standard.value(forKey: "keyboardHeight") as? (Int) {
moveTextField(myTextField, moveDistance: -height as Int, moveDuration: 0.43, up: true)
}else{
UserDefaults.standard.set(keyboardHeight, forKey: "keyboardHeight")
moveTextField(myTextField, moveDistance: -keyboardHeight, moveDuration: 0.43, up: true)
}
}
}
func keyboardWillHide(notification: NSNotification){
if let height = UserDefaults.standard.value(forKey: "keyboardHeight") as? (Int) {
moveTextField(myTextField, moveDistance: -height as Int, moveDuration: 0.25, up: false)
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func moveTextField(_ textField: UITextField, moveDistance: Int, moveDuration: Double, up: Bool) {
let movement: CGFloat = CGFloat(up ? moveDistance : -moveDistance)
UIView.beginAnimations("animateTextField", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(moveDuration)
self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
UIView.commitAnimations()
}
}
你也可以上下移动只有UITextFiled而不是整个屏幕(UIView)。 用这种方法。
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)
And
@objc func keyboardWillChange(notification: NSNotification) {
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = targetFrame.origin.y - curFrame.origin.y
UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
self.textField.frame.origin.y+=deltaY
},completion: nil)
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0{
// self.view.frame.origin.y += keyboardSize.height
self.view.frame.origin.y = 0
}
}
}
我看到所有的答案都是通过键盘高度的值移动视图本身。好吧,我有一个详细的答案,这可能是有用的,如果你正在使用约束即自动布局,移动一个视图通过改变其约束值(底部或顶部约束为例)由一个预定义的值或你可以使用键盘大小值。
在这个例子中,我使用底部约束从文本字段到底部布局视图的初始值为175。
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}
func keyboardWillShow(notification: NSNotification) {
//To retrieve keyboard size, uncomment following line
//let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
bottomConstraint.constant = 260
UIView.animateWithDuration(0.3) {
self.view.layoutIfNeeded()
}
}
func keyboardWillHide(notification: NSNotification) {
//To retrieve keyboard size, uncomment following line
//let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
bottomConstraint.constant = 175
UIView.animateWithDuration(0.3) {
self.view.layoutIfNeeded()
}
}