使用iOS SDK:

我有一个带UITextFields的UIView,可以启动键盘。我需要它能够:

启动键盘后,允许滚动UIScrollView的内容以查看其他文本字段自动“跳转”(通过向上滚动)或缩短

我知道我需要一个UIScrollView。我已经尝试将UIView的类更改为UIScrollView,但仍然无法上下滚动文本框。

我需要UIView和UIScrollView吗?一个在另一个里面吗?

要自动滚动到活动文本字段,需要执行哪些操作?

理想情况下,尽可能多的组件设置将在Interface Builder中完成。我只想编写需要的代码。

注意:我使用的UIView(或UIScrollView)是由一个选项卡(UITabBar)启动的,它需要正常工作。


我正在添加滚动条,只为键盘出现时使用。尽管不需要它,但我觉得它提供了一个更好的界面,例如,用户可以滚动和更改文本框。

当键盘上下移动时,我可以改变UIScrollView的框架大小。我只是在使用:

-(void)textFieldDidBeginEditing:(UITextField *)textField {
    //Keyboard becomes visible
    scrollView.frame = CGRectMake(scrollView.frame.origin.x,
                                  scrollView.frame.origin.y,
    scrollView.frame.size.width,
    scrollView.frame.size.height - 215 + 50);   // Resize
}

-(void)textFieldDidEndEditing:(UITextField *)textField {
    // Keyboard will hide
    scrollView.frame = CGRectMake(scrollView.frame.origin.x,
                                  scrollView.frame.origin.y,
                                  scrollView.frame.size.width,
                                  scrollView.frame.size.height + 215 - 50); // Resize
}

然而,这不会自动“向上移动”或将可见区域中的下部文本字段居中,这是我真正想要的。


当前回答

只需将其添加到pod文件->pod“IQKeyboardManager”

这就是它,处理所有的键盘,滚动视图和一切!

你不需要编写任何代码,找不到更好的解决方案!

它有一个扩展,如果有多个文本字段,它可以处理文本字段显示、屏幕移动、下一个和上一个箭头。

它还有一个自定义完成按钮,可以删除。

链接->https://github.com/hackiftekhar/IQKeyboardManager

其他回答

我迟到了一点。您应该在viewController上添加scrollView。

您必须实现以下2种方法。

TextField委托方法。

    - (void)textFieldDidBeginEditing:(UIView *)textField {
    [self scrollViewForTextField:reEnterPINTextField];
}

然后在委托方法中调用以下方法。

 - (void)scrollViewForTextField:(UIView *)textField {
    NSInteger keyboardHeight = KEYBOARD_HEIGHT;

    if ([textField UITextField.class]) {
        keyboardHeight += ((UITextField *)textField).keyboardControl.activeField.inputAccessoryView.frame.size.height;
    } 

    CGRect screenFrame = [UIScreen mainScreen].bounds;
    CGRect aRect = (CGRect){0, 0, screenFrame.size.width, screenFrame.size.height - ([UIApplication sharedApplication].statusBarHidden ? 0 : [UIApplication sharedApplication].statusBarFrame.size.height)};
    aRect.size.height -= keyboardHeight;
    CGPoint relativeOrigin = [UIView getOriginRelativeToScreenBounds:textField];
    CGPoint bottomPointOfTextField = CGPointMake(relativeOrigin.x, relativeOrigin.y + textField.frame.size.height);

    if (!CGRectContainsPoint(aRect, bottomPointOfTextField) ) {
        CGPoint scrollPoint = CGPointMake(0.0, bottomPointOfTextField.y -aRect.size.height);
        [contentSlidingView setContentOffset:scrollPoint animated:YES];
    }
}

添加我的5美分:)

我总是喜欢使用tableView作为inputTextField或scrollView。结合通知,您可以轻松管理此类行为。(注意,如果您在tableView中使用静态单元格,则这种行为将自动为您管理。)

// MARK: - Notifications
fileprivate func registerNotificaitions() {
    NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillAppear(_:)),
                                           name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillDisappear),
                                           name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

fileprivate func unregisterNotifications() {
    NotificationCenter.default.removeObserver(self)
}

@objc fileprivate func keyboardWillAppear(_ notification: Notification) {
    if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
        view.layoutIfNeeded()
        UIView.animate(withDuration: 0.3, animations: {
            let heightInset = keyboardHeight - self.addDeviceButton.frame.height
            self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: heightInset, right: 0)
            self.view.layoutIfNeeded()
        }, completion: nil)
    }
}

@objc fileprivate func keyboardWillDisappear() {
    view.layoutIfNeeded()
    UIView.animate(withDuration: 0.3, animations: {
        self.tableView.contentInset = UIEdgeInsets.zero
        self.view.layoutIfNeeded()
    }, completion: nil)
}

我认为如果您使用Swift,最好的方法是使用面向协议的编程。

首先,您必须创建KeyboardCapable协议,使符合该协议的任何UIViewController都能够注册和注销键盘观察员:

import Foundation
import UIKit

protocol KeyboardCapable: KeyboardAnimatable {
    func keyboardWillShow(notification: NSNotification)
    func keyboardWillHide(notification: NSNotification)
}

extension KeyboardCapable where Self: UIViewController {
    func registerKeyboardNotifications() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil)
    }

    func unregisterKeyboardNotifications() {
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    }
}

您已经注意到上述代码中有一个无关的KeyboardAnimatable关键字。这只是我们需要创建的下一个协议的名称:

import Foundation
import UIKit

protocol KeyboardAnimatable {

}

extension KeyboardAnimatable where Self: UIViewController {
    func performKeyboardShowFullViewAnimation(withKeyboardHeight height: CGFloat, andDuration duration: NSTimeInterval) {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            self.view.frame = CGRectMake(view.frame.origin.x, -height, view.bounds.width, view.bounds.height)
            }, completion: nil)
    }

    func performKeyboardHideFullViewAnimation(withDuration duration: NSTimeInterval) {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            self.view.frame = CGRectMake(view.frame.origin.x, 0.0, view.bounds.width, view.bounds.height)
            }, completion: nil)
    }
}

这个KeyboardAnimatable协议为所有符合它的UIViewController提供了两种方法,分别为整个视图上下设置动画。

好的,如果KeyboardCapable符合KeyboardAnimatable,则所有符合Keyboard Capable的UIViewController也符合KeyboaardAnimatable。这很酷。

让我们看看符合KeyboardCapable的UIViewController,并对键盘事件做出反应:

import Foundation
import UIKit

class TransferConfirmViewController: UIViewController, KeyboardCapable {
    //MARK: - LIFE CYCLE       
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        registerKeyboardNotifications()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)

        unregisterKeyboardNotifications()
    }

    //MARK: - NOTIFICATIONS
    //MARK: Keyboard
    func keyboardWillShow(notification: NSNotification) {
        let keyboardHeight = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height
        let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        performKeyboardShowFullViewAnimation(withKeyboardHeight: keyboardHeight, andDuration: animationDuration)
    }

    func keyboardWillHide(notification: NSNotification) {
        let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        performKeyboardHideFullViewAnimation(withDuration: animationDuration)
    }
}

现在,您的UIViewController将响应键盘事件,并将因此产生动画效果。

注意:如果您想要自定义动画而不是推拉视图,则必须在KeyboardAnimatable协议上定义自定义方法或在Keyboard功能上执行这些方法。这取决于你。

从以下链接下载TPKeyBoardAvoiding:https://github.com/michaeltyson/TPKeyboardAvoiding. 展开zipped文件夹,找到TPKeyboardAvoiding文件夹。选择所有.h和.m文件,并将其放到项目中。确保选中了复制项(如果需要)。将UIScrollView拖放到StoryBoard并与TPKeyboardAvoidingScrollView关联。现在,您可以在滚动视图的顶部添加UI元素。注意,即使在拖动scrollView之后,这个类也会检测UI元素的触摸。

在ViewController上:

@IBOutlet weak var usernameTextfield: UITextField!
@IBOutlet weak var passwordTextfield: UITextField!
@IBOutlet weak var loginScrollView: UIScrollView!


override func viewWillAppear(animated: Bool) {
        loginScrollView.scrollEnabled =  false
    }

添加TextField委托。

//MARK:- TEXTFIELD METHODS
func textFieldShouldReturn(textField: UITextField) -> Bool
{
    if (usernameTextfield.resignFirstResponder())
    {
        passwordTextfield.becomeFirstResponder()
    }
    textField.resignFirstResponder();
    loginScrollView!.setContentOffset(CGPoint.zero, animated: true);
    loginScrollView.scrollEnabled =  false
    return true
}
func textFieldDidBeginEditing(textField: UITextField)
{
    loginScrollView.scrollEnabled =  true

    if (textField.tag  == 1 && (device == "iPhone" || device == "iPhone Simulator" || device == "iPod touch"))
    {
        let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.origin.y/6.4);
        loginScrollView!.setContentOffset(scrollPoint, animated: true);

    }
    else if (textField.tag  == 2 && (device == "iPhone" || device == "iPhone Simulator" || device == "iPod touch"))
    {
        let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.origin.y/6.0);
        loginScrollView!.setContentOffset(scrollPoint, animated: true);
    }
}
func textFieldDidEndEditing(textField: UITextField)
{
    loginScrollView!.setContentOffset(CGPointZero,animated: true);
}

仅使用文本字段:

1a)使用界面生成器:选择所有文本字段=>编辑=>嵌入=>滚动视图

1b)在UIScrollView中手动嵌入文本字段,称为scrollView

2) 设置UITextFieldDelegate

3) 设置每个textField.delegate=self;(或在Interface Builder中建立连接)

4) 复制/粘贴:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    CGPoint scrollPoint = CGPointMake(0, textField.frame.origin.y);
    [scrollView setContentOffset:scrollPoint animated:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    [scrollView setContentOffset:CGPointZero animated:YES];
}