我有一个应用,它在视图的下半部分有一个文本框。 这意味着当我在文本框中输入时,键盘会覆盖文本框。
我如何在打字时向上移动视图,这样我就可以看到我键入的内容,然后在键盘消失时将它移回原来的位置?
我到处都看了,但所有的解似乎都在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
}
}
其他回答
我已经阅读了答案,并通过以下代码行解决了我的问题:
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var titleField: UITextField!
@IBOutlet weak var priceField: UITextField!
@IBOutlet weak var detailsField: UTtextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do not to forget to set the delegate otherwise the textFieldShouldReturn(_:)
// won't work and the keyboard will never be hidden.
priceField.delegate = self
titleField.delegate = self
detailsField.delegate = self
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 textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
func keyboardWillShow(notification: NSNotification) {
var translation:CGFloat = 0
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if detailsField.isEditing{
translation = CGFloat(-keyboardSize.height)
}else if priceField.isEditing{
translation = CGFloat(-keyboardSize.height / 3.8)
}
}
UIView.animate(withDuration: 0.2) {
self.view.transform = CGAffineTransform(translationX: 0, y: translation)
}
}
func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.2) {
self.view.transform = CGAffineTransform(translationX: 0, y: 0)
}
}
}
我有几个UITextFields,并希望视图移动不同取决于哪个textField被点击。
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)
}
使用以下代码查看UITextField单击
func textFieldDidBeginEditing(textField: UITextField) {
ViewUpanimateMoving(true, upValue: 100)
}
func textFieldDidEndEditing(textField: UITextField) {
ViewUpanimateMoving(false, upValue: 100)
}
func ViewUpanimateMoving (up:Bool, upValue :CGFloat){
var durationMovement:NSTimeInterval = 0.3
var movement:CGFloat = ( up ? -upValue : upValue)
UIView.beginAnimations( "animateView", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(durationMovement)
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
UIView.commitAnimations()
}
我看到所有的答案都是通过键盘高度的值移动视图本身。好吧,我有一个详细的答案,这可能是有用的,如果你正在使用约束即自动布局,移动一个视图通过改变其约束值(底部或顶部约束为例)由一个预定义的值或你可以使用键盘大小值。
在这个例子中,我使用底部约束从文本字段到底部布局视图的初始值为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()
}
}
Swift 3
func textFieldDidBeginEditing(_ textField: UITextField) { // became first responder
//move textfields up
let myScreenRect: CGRect = UIScreen.main.bounds
let keyboardHeight : CGFloat = 216
UIView.beginAnimations( "animateView", context: nil)
var movementDuration:TimeInterval = 0.35
var needToMove: CGFloat = 0
var frame : CGRect = self.view.frame
if (textField.frame.origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height > (myScreenRect.size.height - keyboardHeight - 30)) {
needToMove = (textField.frame.origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height) - (myScreenRect.size.height - keyboardHeight - 30);
}
frame.origin.y = -needToMove
self.view.frame = frame
UIView.commitAnimations()
}
func textFieldDidEndEditing(_ textField: UITextField) {
//move textfields back down
UIView.beginAnimations( "animateView", context: nil)
var movementDuration:TimeInterval = 0.35
var frame : CGRect = self.view.frame
frame.origin.y = 0
self.view.frame = frame
UIView.commitAnimations()
}