UITextView外的光标问题

7
我已经搜遍了各种资料,但似乎找不到答案。最接近的是这里:UITextView cursor below frame when changing frame
非常抱歉,由于我的声望(几乎)为零,无法提供截图证明,但它看起来与链接的SO帖子类似。
当我在iOS6上运行应用程序时,一切正常(内容随光标滚动以使其保持在屏幕上),但在iOS7上,光标超过了UITextView的末尾一行。 我尝试添加UIEdgeInsets来移动内容,但当用户正在输入文本时,它会不断添加新行,直到光标位于文本视图的末尾以下。
我的布局包括一个标签(headerText),下面是UITextView(textView)。 从选项卡栏中显示此视图。有一个键盘输入附件,但在调用函数之前,它的高度会自动计算到键盘高度中。
这是我用来调整视图大小的功能,从keyboard show/hide委托,旋转,初始布局等中调用:
-(void)resizeViewsWithKbdHeight:(float)kbHeight
{
    //set the header label frame

    //set constraints
    //total view width - 30 (15 each for left and right padding)
    CGFloat labelWidth = ([[[self navigationController] view] bounds].size.width - 30);
    CGSize constraintSize = {labelWidth, CGFLOAT_MAX};
    //calculate needed height for header label
    CGSize textSize = [[self headerText] sizeWithFont:[UIFont systemFontOfSize:17.0f]
                                    constrainedToSize:constraintSize
                                        lineBreakMode:NSLineBreakByWordWrapping];
    //build and set frame for header label:
    //make it the same as the old
    CGRect headerTempSize = [[self headerLabel] frame];
    //except for the height
    headerTempSize.size.height = textSize.height;
    //and set it
    [[self headerLabel] setFrame:headerTempSize];

    //correct the placement of the UITextView, so it's under the header label

    //build a new frame based on current textview frame
    CGRect newFrame = [[self textView] frame];

    //get the y position of the uitextview, the +8 is the padding between header and uitextview
    CGFloat vertPadding = [[self headerLabel] frame].origin.y + [[self headerLabel] frame].size.height + 8;

    //bump it down vertically
    newFrame.origin.y = vertPadding;

    //bump things down by the amount of the navigation bar and status bar
    float offscreenBump = [[[self navigationController] navigationBar] frame].origin.y + [[[self navigationController] navigationBar] frame].size.height;

    //if we aren't showing the keyboard, add the height of the tab bar
    if(kbHeight == 0) {
        offscreenBump += [[[self tabBarController] tabBar] frame].size.height;
    }

    //calculate the new height of the textview, the +9 is for padding below the text view
    CGFloat newHeight = [[[self navigationController] view] bounds].size.height - ([[self textView] frame].origin.y + 9 + kbHeight + offscreenBump);

    //resize the height as calculated
    newFrame.size.height = newHeight;

    //set textview frame to this new frame
    [[self textView] setFrame:newFrame];
}

我正在尝试支持iOS5,因此不能使用自动布局。

可能我对我的做法过于天真。

提前感谢!


是的,当键盘调用时调整视图大小确实很麻烦。但是我在GitHub上找到了一个名为“EKKeyboardAvoiding”的开源项目。如果你想尝试一下,那就没问题了。它会在键盘调用时按需调整滚动视图的大小。你可以将其用于任何滚动视图子类。 - Dinesh Raja
2个回答

7

这似乎是iOS 7中的一个bug。我发现唯一纠正此问题的方法是为UITextView添加一个代理并实现textViewDidChangeSelection,将视图重置以显示所选内容,如下:

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

- (void) textViewDidChangeSelection: (UITextView *) tView {
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        [tView scrollRangeToVisible:[tView selectedRange]];
    }
}

谢谢Mike,这似乎可以工作,尽管不是理想的,因为他们必须在看不见的行上输入才能滚动(除非我错过了什么)。 - jordan.roskelley
他们确实需要以某种方式将光标放在那里,因为它会根据光标位置滚动。如果你在文本末尾,这样是行不通的,除非你添加一个换行符。这就是你遇到的问题吗? - Mike
是的,现在(经过您的修复)行为是当光标到达末尾时,它会移动到文本视图的下一行,然后一旦他们在看不见的行上输入文本,它就会向上滚动一行。 - jordan.roskelley

6
我发现了一种更加hack的但更有效的解决问题的方法:
- (void)textViewDidChangeSelection:(UITextView *)textView
{
    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        if ([textView.text characterAtIndex:textView.text.length-1] != ' ') {
            textView.text = [textView.text stringByAppendingString:@" "];
        }

        NSRange range0 = textView.selectedRange;
        NSRange range = range0;
        if (range0.location == textView.text.length) {
            range = NSMakeRange(range0.location - 1, range0.length);
        } else if (range0.length > 0 &&
                   range0.location + range0.length == textView.text.length) {
            range = NSMakeRange(range0.location, range0.length - 1);
        }
        if (!NSEqualRanges(range, range0)) {
            textView.selectedRange = range;
        }
    }
}

我确保文本字段中始终有一个尾随空格。然后,如果用户尝试更改选择以显示空格,则更改选择。通过始终在光标前保留空格,字段会按照预期滚动。

最后,如果需要,在将文本复制到模型中时删除尾随空格(未显示)。


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