我的代码有问题.当我在编辑本应被键盘弹出隐藏的UITextField时,我正在try 移动UIScrollView.

我现在正在移动主框架,因为我不知道如何在代码中"向上滚动". 所以,我做了一些代码,它工作得很好,但是当我编辑一个UItextfield并切换到另一个UITextField,而没有按下‘Return’按钮,主视图就会变成waaayyyy到更高的位置.

我用变量大小、距离和textFieldRect计算了NSLog().起源正如你在下面看到的.当我把两个UITextField放在同一个位置(y原点)并进行这个特殊的"切换"(不按回车键)时,我得到的数字是相同的,而我的代码在第一次编辑UITextField时运行良好,但在第二次编辑时运行不好.

看看这个:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
{
    int size;
    CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
    size = textFieldRect.origin.y + textFieldRect.size.height;
    if (change == FALSE)
    {
        size = size - distance;
    }
    if (size < PORTRAIT_KEYBOARD_HEIGHT)
    {
        distance = 0;
    }
    else if (size > PORTRAIT_KEYBOARD_HEIGHT)
    {
        distance = size - PORTRAIT_KEYBOARD_HEIGHT + 5; // +5 px for more visibility
    }
    NSLog(@"origin %f", textFieldRect.origin.y);
    NSLog(@"size %d", size);
    NSLog(@"distance %d", distance);
    CGRect viewFrame = self.view.frame;
    viewFrame.origin.y -= distance;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
    change = FALSE;
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    change = TRUE;
    CGRect viewFrame = self.view.frame;
    viewFrame.origin.y += distance;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
}

有什么 idea 吗?

推荐答案

苹果公司推荐的方法是改变UIScrollView中的contentInset.这是一个非常优雅的解决方案,因为你不必搞乱contentSize.

// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(keyboardWasShown:)
            name:UIKeyboardDidShowNotification object:nil];
   [[NSNotificationCenter defaultCenter] addObserver:self
             selector:@selector(keyboardWillBeHidden:)
             name:UIKeyboardWillHideNotification object:nil];
}

// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;

    // If active text field is hidden by keyboard, scroll it so it's visible
    // Your application might not need or want this behavior.
    CGRect aRect = self.view.frame;
    aRect.size.height -= kbSize.height;
    if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
        CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
}

// Called when the UIKeyboardWillHideNotification is sent    
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;
}

Swift version:

func registerForKeyboardNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardAppear(_:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardDisappear(_:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
}

// Don't forget to unregister when done
deinit {
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidHide, object: nil)
}

@objc func onKeyboardAppear(_ notification: NSNotification) {
    let info = notification.userInfo!
    let rect: CGRect = info[UIKeyboardFrameBeginUserInfoKey] as! CGRect
    let kbSize = rect.size

    let insets = UIEdgeInsetsMake(0, 0, kbSize.height, 0)
    scrollView.contentInset = insets
    scrollView.scrollIndicatorInsets = insets

    // If active text field is hidden by keyboard, scroll it so it's visible
    // Your application might not need or want this behavior.
    var aRect = self.view.frame;
    aRect.size.height -= kbSize.height;

    let activeField: UITextField? = [addressTextView, servicePathTextView, usernameTextView, passwordTextView].first { $0.isFirstResponder }
    if let activeField = activeField {
        if !aRect.contains(activeField.frame.origin) {
            let scrollPoint = CGPoint(x: 0, y: activeField.frame.origin.y-kbSize.height)
            scrollView.setContentOffset(scrollPoint, animated: true)
        }
    }
}

@objc func onKeyboardDisappear(_ notification: NSNotification) {
    scrollView.contentInset = UIEdgeInsets.zero
    scrollView.scrollIndicatorInsets = UIEdgeInsets.zero
}

Ios相关问答推荐

阿拉伯文变音符号(Harakat)在文本对齐的UILabel中未对齐

TrueDepth摄像机像素距离不准确

ScrollViewReader Scrollto Not Working

在flatter_riverpod中,如果没有ref对象,我们如何访问提供程序?

如何在@AppStorage中存储字体?

SwiftUI:.toolbar 不适用于 UITextView

在最新版本的 iOS 中,设备上的Localized.strings文件发生了什么变化?

如何创建装饰视图?

保存和读取登录到 keys 串不工作 IOS swift

如何在用户点击的位置使用SceneKit渲染球体?

@Query与SwiftData数据列表绑定

归档时命令 PhaseScriptExecution 失败,退出代码非零

Flutter 构建 ios 失败:运行 pod 安装时出错

Swift Combine 防止初始值触发接收器并同时防止重复?

通过 Rosetta 打开模拟器 xcode 14 以修复滚动

如何将 ImageView 放置在 UIView 的中心?

检测 iPhone/iPad/iPod touch 的 colored颜色 ?

iOS WKWebView 不显示 javascript alert() 对话框

在滚动视图中使用动态大小的控制器调整容器视图的大小

我可以在 UIScrollView 中使用 UIRefreshControl 吗?