热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

仅在键盘覆盖输入字段时才向上移动视图

如何解决《仅在键盘覆盖输入字段时才向上移动视图》经验,为你挑选了5个好方法。

我正在尝试为iPhone构建输入屏幕.屏幕有许多输入字段.其中大多数位于屏幕顶部,但两个字段位于底部.当用户尝试编辑屏幕底部的文本时,键盘将弹出并覆盖屏幕.我找到了一个简单的解决方案,可以在发生这种情况时将屏幕向上移动,但结果是屏幕总是向上移动,当用户尝试编辑屏幕时,屏幕顶部的字段会移动.

有没有办法让屏幕在编辑底部字段时移动?

我使用了这里找到的代码:

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(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}

func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y += 150
}

Nerkyator.. 206

Apple在本文档中对您的问题进行了详细解释.此页面上的示例代码(at Listing 4-1)完全符合您的需要,只有在当前编辑应位于键盘下方时才会滚动视图.您只需要将所需的控件放在scrollViiew中.唯一的问题是这是Objective-C,我认为你需要它在Swift中...所以它是:它是:

声明一个变量

var activeField: UITextField?

然后添加这些方法

 func registerForKeyboardNotifications()
{
    //Adding notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}


func deregisterFromKeyboardNotifications()
{
    //Removing notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWasShown(notification: NSNotification)
{
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.scrollEnabled = true
    var info : NSDictiOnary= notification.userInfo!
    var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
    var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

    self.scrollView.cOntentInset= contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height
    if let activeFieldPresent = activeField
    {
        if (!CGRectContainsPoint(aRect, activeField!.frame.origin))
        {
            self.scrollView.scrollRectToVisible(activeField!.frame, animated: true)
        }
    }


}


func keyboardWillBeHidden(notification: NSNotification)
{
    //Once keyboard disappears, restore original positions
    var info : NSDictiOnary= notification.userInfo!
    var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
    var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0)
    self.scrollView.cOntentInset= contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.scrollEnabled = false

}

func textFieldDidBeginEditing(textField: UITextField!)
{
    activeField = textField
}

func textFieldDidEndEditing(textField: UITextField!)
{
    activeField = nil
}

请务必将ViewController声明为UITextFieldDelegate初始化方法并在初始化方法中设置正确的委托:ex:

self.you_text_field.delegate = self

并记得调用registerForKeyboardNotificationsviewInit并deregisterFromKeyboardNotifications退出.

编辑/更新:Swift 4.2语法

func registerForKeyboardNotifications(){
    //Adding notifies on keyboard appearing
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}

func deregisterFromKeyboardNotifications(){
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWasShown(notification: NSNotification){
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 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.activeField {
        if (!aRect.contains(activeField.frame.origin)){
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
}

@objc func keyboardWillBeHidden(notification: NSNotification){
    //Once keyboard disappears, restore original positions
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 0.0)
    self.scrollView.cOntentInset= contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.isScrollEnabled = false
}

func textFieldDidBeginEditing(_ textField: UITextField){
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}

谢谢,这正是我想要的 - 苹果推荐的解决方案.但是,在我的情况下,我已经有一个跨越可视区域的滚动视图.此代码将在键盘隐藏后禁用滚动.我删除了"self.scrollView.scrollEnabled = false",它仍然不会滚动.对我有用的是"self.scrollView.cOntentInset= UIEdgeInsetsZero;" 在keyboardWillHide事件中的这一行 (10认同)

完美的代码.但我需要使用`UIKeyboardFrameEndUserInfoKey`而不是'UIKeyboardFrameBeginUserInfoKey`,因为后者返回高度为0.并且将hittest点更改为底部而不是原点.`if let activeField = self.activeField {var point = activeField.frame.origin point.y + = activeField.frame.size.height if(!aRect.contains(point)){self.scrollView.scrollRectToVisible(activeField.frame,动画:true)}}` (5认同)

您必须在viewDidLoad上调用registerForKeyboardNotifications,因此您将向观察中心添加一个观察者,以了解键盘何时出现或从屏幕上消失。当这些通知触发时,将调用方法keyboardWasShown和keyboardWillBeHidden,然后scrollview将根据键盘大小移动。您可以在此处找到有关NotificationCenter的更多详细信息:https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/ (2认同)

@MaX:它应该可以工作,但是如果你想要一个Swift4解决方案你可以查看[这个iOS示例](https://github.com/mattneub/Programming-iOS-Book-Examples/blob/swift4ios11/bk2ch10p522textFieldScrollView/ch23p805textFieldSliding/ViewController .swift)来自[Matt Neuburg](/sf/ask/17360801/)的书,我向所有iOS开发者推荐:) (2认同)


Mr H.. 131

这是我的2美分:

您是否尝试过:https://github.com/hackiftekhar/IQKeyboardManager

非常容易安装Swift或Objective-C.

它是如何工作的:

IQKeyboardManager(Swift): - IQKeyboardManagerSwift可通过CocoaPods获得,安装它只需将以下行添加到您的Podfile:(#236)

pod 'IQKeyboardManagerSwift'

在AppDelegate.swift中,只需导入IQKeyboardManagerSwift框架并启用IQKeyboardManager.

import IQKeyboardManagerSwift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    IQKeyboardManager.sharedManager().enable = true
    // For Swift 4, use this instead
    // IQKeyboardManager.shared.enable = true


    return true
    }
}

这就是全部.简单!



1> Nerkyator..:

Apple在本文档中对您的问题进行了详细解释.此页面上的示例代码(at Listing 4-1)完全符合您的需要,只有在当前编辑应位于键盘下方时才会滚动视图.您只需要将所需的控件放在scrollViiew中.唯一的问题是这是Objective-C,我认为你需要它在Swift中...所以它是:它是:

声明一个变量

var activeField: UITextField?

然后添加这些方法

 func registerForKeyboardNotifications()
{
    //Adding notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}


func deregisterFromKeyboardNotifications()
{
    //Removing notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWasShown(notification: NSNotification)
{
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.scrollEnabled = true
    var info : NSDictiOnary= notification.userInfo!
    var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
    var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

    self.scrollView.cOntentInset= contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height
    if let activeFieldPresent = activeField
    {
        if (!CGRectContainsPoint(aRect, activeField!.frame.origin))
        {
            self.scrollView.scrollRectToVisible(activeField!.frame, animated: true)
        }
    }


}


func keyboardWillBeHidden(notification: NSNotification)
{
    //Once keyboard disappears, restore original positions
    var info : NSDictiOnary= notification.userInfo!
    var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
    var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0)
    self.scrollView.cOntentInset= contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.scrollEnabled = false

}

func textFieldDidBeginEditing(textField: UITextField!)
{
    activeField = textField
}

func textFieldDidEndEditing(textField: UITextField!)
{
    activeField = nil
}

请务必将ViewController声明为UITextFieldDelegate初始化方法并在初始化方法中设置正确的委托:ex:

self.you_text_field.delegate = self

并记得调用registerForKeyboardNotificationsviewInit并deregisterFromKeyboardNotifications退出.

编辑/更新:Swift 4.2语法

func registerForKeyboardNotifications(){
    //Adding notifies on keyboard appearing
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}

func deregisterFromKeyboardNotifications(){
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWasShown(notification: NSNotification){
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 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.activeField {
        if (!aRect.contains(activeField.frame.origin)){
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
}

@objc func keyboardWillBeHidden(notification: NSNotification){
    //Once keyboard disappears, restore original positions
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 0.0)
    self.scrollView.cOntentInset= contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.isScrollEnabled = false
}

func textFieldDidBeginEditing(_ textField: UITextField){
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}


谢谢,这正是我想要的 - 苹果推荐的解决方案.但是,在我的情况下,我已经有一个跨越可视区域的滚动视图.此代码将在键盘隐藏后禁用滚动.我删除了"self.scrollView.scrollEnabled = false",它仍然不会滚动.对我有用的是"self.scrollView.cOntentInset= UIEdgeInsetsZero;" 在keyboardWillHide事件中的这一行
完美的代码.但我需要使用`UIKeyboardFrameEndUserInfoKey`而不是'UIKeyboardFrameBeginUserInfoKey`,因为后者返回高度为0.并且将hittest点更改为底部而不是原点.`if let activeField = self.activeField {var point = activeField.frame.origin point.y + = activeField.frame.size.height if(!aRect.contains(point)){self.scrollView.scrollRectToVisible(activeField.frame,动画:true)}}`
您必须在viewDidLoad上调用registerForKeyboardNotifications,因此您将向观察中心添加一个观察者,以了解键盘何时出现或从屏幕上消失。当这些通知触发时,将调用方法keyboardWasShown和keyboardWillBeHidden,然后scrollview将根据键盘大小移动。您可以在此处找到有关NotificationCenter的更多详细信息:https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/
@MaX:它应该可以工作,但是如果你想要一个Swift4解决方案你可以查看[这个iOS示例](https://github.com/mattneub/Programming-iOS-Book-Examples/blob/swift4ios11/bk2ch10p522textFieldScrollView/ch23p805textFieldSliding/ViewController .swift)来自[Matt Neuburg](/sf/ask/17360801/)的书,我向所有iOS开发者推荐:)

2> Mr H..:

这是我的2美分:

您是否尝试过:https://github.com/hackiftekhar/IQKeyboardManager

非常容易安装Swift或Objective-C.

它是如何工作的:

IQKeyboardManager(Swift): - IQKeyboardManagerSwift可通过CocoaPods获得,安装它只需将以下行添加到您的Podfile:(#236)

pod 'IQKeyboardManagerSwift'

在AppDelegate.swift中,只需导入IQKeyboardManagerSwift框架并启用IQKeyboardManager.

import IQKeyboardManagerSwift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    IQKeyboardManager.sharedManager().enable = true
    // For Swift 4, use this instead
    // IQKeyboardManager.shared.enable = true


    return true
    }
}

这就是全部.简单!


完善.这应该默认内置.似乎很荒谬,但事实并非如此.
简单易用且非常有效的工具.
这对我来说不适用于Swift 4.1 IQKeyboardManager.sharedManager().enable = true**已切换到**`IQKeyboardManager.shared.enable = true`

3> Edward..:

我发现对我来说完美的工作是:

func textFieldDidBeginEditing(textField: UITextField) {
    if textField == email || textField == password {
        animateViewMoving(true, moveValue: 100)
    }
}

func textFieldDidEndEditing(textField: UITextField) {
    if textField == email || textField == password {
        animateViewMoving(false, moveValue: 100)
    }
}

func animateViewMoving (up:Bool, moveValue :CGFloat){
    let movementDuration:NSTimeInterval = 0.3
    let movement:CGFloat = ( up ? -moveValue : moveValue)

    UIView.beginAnimations("animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration)

    self.view.frame = CGRectOffset(self.view.frame, 0, movement)
    UIView.commitAnimations()
}

您还可以更改高度值.如果要将其用于所有文本字段,请删除"if语句".

您甚至可以将此用于需要用户输入的所有控件,如TextView.


直接移动UIView框架不是一个很好的解决方案.此外,这包括特定于此用例的硬编码值.我鼓励人们不要实现这样的解决方案,而是做一些更接近最佳实践的事情,如接受的答案所述.

4> 小智..:

有没有办法让屏幕在编辑底部字段时移动?

我有一个类似的问题,发现一个非常简单的解决方案,而不使用scrollView,而是在keyboardWillShow/Hide方法中使用if语句.

func keyboardWillShow(notification: NSNotification) {
    if bottomText.editing{
        self.view.window?.frame.origin.y = -1 * getKeyboardHeight(notification)
    }
}

func keyboardWillHide(notification: NSNotification) {
    if self.view.window?.frame.origin.y != 0 {
        self.view.window?.frame.origin.y += getKeyboardHeight(notification)
    }
}

这对我来说是一个很好的解决方案,因为我只有两个文本字段.

移动整个视图:仅在编辑某些文本字段(bottomText)时

向下移动整个视图:仅当视图不在原始位置时



5> 小智..:

出现键盘时,只需使用此扩展名即可移动任何UIView。

extension UIView {
    func bindToKeyboard(){
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChange(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
    }

    @objc func keyboardWillChange(_ notification: NSNotification){
        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let beginningFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let endFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue

        let deltaY = endFrame.origin.y - beginningFrame.origin.y

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.frame.origin.y += deltaY
        }, completion: nil)
    }
}

然后在viewdidload中将视图绑定到键盘

UiView.bindToKeyboard()


推荐阅读
author-avatar
卖火柴的冰枫_939
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有