iOS7下如何使UITextView高度等于屏幕高度减去键盘高度?

7

我的代码在iOS 6下运行良好,但在iOS 7下,我似乎无法使UITextView的高度等于设备屏幕减去键盘的高度(换句话说,当键盘弹起时,UITextView仍然全屏显示,但不会被键盘覆盖)。

首先,当我将UITextView放在我的视图控制器中(它嵌入了一个导航控制器),它也必须在导航栏下方,否则它会向下偏移太多。

从那里开始,我尝试了所有这些示例:

self.textView.contentInset = UIEdgeInsetsMake(0, 0, 230, 0);
self.textView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, 230, 0);
self.textView.textContainerInset = UIEdgeInsetsMake(0, 0, 230, 0);

在每个键盘上,仍然会在某些点上覆盖文本视图。我还尝试设置高度约束并操作常量,但没有成功。

self.height.constant = self.height.constant - 240.0;

(其中height是约束输出口。)

这些都已经尝试过,在[self.textField becomeFirstResponder];调用之前和之后。

我该如何完成这个任务? 我只想要一个全屏的UITextView,其中插入符不会进入键盘下面,但在iOS 7下实现这样的基本功能似乎很困难。

2个回答

3
“正确”的方法是在iOS7之前调整UITextView(UIScrollView子类)的contentInset属性,以便在键盘显示或隐藏时进行调整。我个人没有进行调查,但这似乎在iOS7中效果不佳,因为底部插入要么不被尊重,要么光标仍然会进入键盘以下区域。参见此问题以供参考。 在您使用自动布局且只需“全屏”文本视图的情况下,您可以在键盘显示或隐藏时简单地调整一个约束。这将调整您的文本视图的高度:
@implementation TSViewController
{
    IBOutlet NSLayoutConstraint* _textViewSpaceToBottomConstraint;
}

- (void) dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver: self];
}

- (void)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];
}

- (void) keyboardWillShow: (NSNotification*) n
{
    NSValue* bv = n.userInfo[UIKeyboardFrameEndUserInfoKey];
    CGRect br = [bv CGRectValue];

    _textViewSpaceToBottomConstraint.constant = br.size.height;
}

- (void) keyboardWillHide: (NSNotification*) n
{
    _textViewSpaceToBottomConstraint.constant = 0;
}

@end

在你的故事板中,将UITextView拖放到视图控制器视图上,并添加4个约束将其边缘粘合到视图控制器视图的边缘。将底部空间约束连接到视图控制器中的IBOutlet _textViewSpaceToBottomConstraint。
你可以尝试在动画块内调整大小,从键盘通知中借用动画时间和曲线。
我想看到一个设置contentInset并正常工作的版本...

enter image description here

编辑

这里有另一个与此主题相关且有解决方案的SO问题。 显然,光标(光标)超出框架的问题与我上面提到的“正确”方法是相同的,即设置contentInset属性。因此,解决此问题的修复程序应使您能够仅通过调整contentInset而不是更改文本视图帧(通过.frame或通过约束)来解决该问题。

编辑2

最后一点想法。在iOS7中,键盘是半透明的。用户应该能够看到键盘后面的内容。通过将UITextView调整为位于键盘之上,这永远不会发生。因此,“正确”的解决方案仍然是调整文本视图底部的contentInset,将键盘的高度添加到文本视图的可滚动区域中。然后,在理想情况下,当键盘出现时,您将调整文本视图的contentOffset以使光标保持可见状态。最后,将其添加到'fix',以便在显示键盘但用户正在输入换行符时将插入符号位置保持在键盘上方。


使用这个解决方案,当我输入一定数量时,它会变成这样:http://cl.ly/image/2A320J3y2d3A - Doug Smith
这显然是iOS7的一个bug。请参考这个问题:https://dev59.com/T2Ik5IYBdhLWcg3wdd4l。我将解决方法应用到了你的示例中,它可以修复这个问题。 - TomSwift
也可以查看这个问题。它涵盖了光标超出框架的问题,以及将解决方案与contentInset方法相结合(而不是更改文本视图框架)的方法:https://dev59.com/1WMl5IYBdhLWcg3wZWSD - TomSwift
第二种解决方案似乎需要更多的工作,但结果与第一种相同,所以我选择了第一种,并且效果很好。干杯 :) (等系统允许时将授予奖励)。 - Doug Smith
那只能部分地解决问题...是的,它确实可以将文本保持在键盘上方,但旋转设备后,它会出现奇怪的情况。文本现在被限制在视图的中心。我在iOS6中遇到了这个问题,并找到了一个适用于所有方向的解决方法。 - Marc Watson
尝试使用以下代码来处理不同的方向:_textViewSpaceToBottomConstraint.constant = UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? br.size.height : br.size.width; - fal

1
在iOS7中解决这个问题的方法是将表视图放入容器视图中,这个容器视图成为你的主要视图。您可以为其添加约束,使其附加到topLayoutGuide。添加第二个占位符视图,该视图限制在表格顶部并限制在底部的bottomLayoutConstraint上。向此占位符视图添加约束,使其高度为0,并保持一个ivar指向它。您可以提供一个UITableViewController子类,该子类重写tableView属性以使用真实的表格视图。

当键盘准备弹出时,您可以从通知中获取表格的高度(以下代码),并对占位符视图的constraint属性进行动画设置,使其等于键盘的高度。

以下是键盘通知代码:

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
    [defaultCenter addObserver:self selector:@selector(keyboardMoving:) name:UIKeyboardWillShowNotification object:nil];
    [defaultCenter addObserver:self selector:@selector(keyboardMoving:) name:UIKeyboardWillHideNotification object:nil];
    [defaultCenter addObserver:self selector:@selector(keyboardMoving:) name:UIKeyboardDidHideNotification object:nil];
}

-(void)viewWillDisappear:(BOOL)animated
{
    NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
    [defaultCenter removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [defaultCenter removeObserver:self name:UIKeyboardWillHideNotification object:nil];
    [defaultCenter removeObserver:self name:UIKeyboardDidHideNotification object:nil];

    [super viewWillDisappear:animated];
}
- (void)keyboardMoving:(NSNotification *)note
{
    NSString *msg = note.name;

    if([msg isEqualToString:UIKeyboardWillShowNotification] && !_keyboardUp) {
        _keyboardUp = YES;
        [[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&_animationDuration];
        [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&_keyboardRect];
        NSLog(@"ORIG KEYBOARD %@", NSStringFromCGRect(_keyboardRect));
        _keyboardRect = [self.view convertRect:_keyboardRect fromView:nil];
        NSLog(@"NEW KEYBOARD %@", NSStringFromCGRect(_keyboardRect));
        _animate = YES;
    } else
    if([msg isEqualToString:UIKeyboardWillHideNotification] && _keyboardUp) {
        _keyboardUp = NO;
        _animate = YES;
    } else
    if([msg isEqualToString:UIKeyboardDidHideNotification]) {
        _keyboardUp = NO;
        _animate = NO;
    }
}

- (BOOL)isKeyboardMovingUp
{
    return _keyboardUp == YES && _animate == YES;
}
- (BOOL)isKeyboardMovingDown
{
    return _keyboardUp == NO && _animate == YES;
}

- (BOOL)isKeyboardDown
{
    return _keyboardUp == NO && _animate == NO;
}

你需要做的是在键盘弹出之前或者一直都要,创建一个空的容器视图并将其添加到中,在该视图中添加表格,添加。

如果我理解你的代码正确,你正在操作矩形,对吗?iOS最近非常推崇自动布局,所以我更喜欢使用涉及它的解决方案。 - Doug Smith
因此,您可以获得键盘的动画速度和大小。假设您的UITextView在主要的vc.view中。在底部添加一个约束条件,在textView底部和父视图之间设置高度为0。当键盘弹出时,创建一个UIView动画,持续时间与键盘弹出相同,并将底部约束常量设置为键盘的高度。哇!现在您的UITextView将以与键盘弹出相同的速率压缩。 - David H
我遇到了与Doug类似的问题...在iOS6中一切都正常工作,但现在它不会自动滚动。我的区别是我正在使用通知。我可以手动滚动。你有一个变量被记录下来... _keyboardUp...它是什么类型的变量?只是一个BOOL吗? - Marc Watson
@MarcWatson 是的 - 只需要一个布尔变量来保存状态。 - David H
我不清楚在这段代码的哪个地方对textview进行了操作? - Doug Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接