iOS 7.1 UITextView在新行之后仍然没有滚动到光标/插入符号

bil*_*tum 25 uitextview ios ios7 ios7.1

从iOS 7开始,UITextView当用户键入流向新行的文本时,a 不会自动滚动到光标.这个问题在SO和其他地方都有详细记载.对我来说,这个问题仍然存在于iOS 7.1中.我究竟做错了什么?

在此输入图像描述

我安装了Xcode 5.1并针对iOS 7.1.我正在使用自动布局.

以下是我将文本视图的内容放在键盘上方的方法:

- (void)keyboardUp:(NSNotification *)notification
{
    NSDictionary *info = [notification userInfo];
    CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

    UIEdgeInsets contentInset = self.textView.contentInset;
    contentInset.bottom = keyboardRect.size.height;
    self.textView.contentInset = contentInset;
}
Run Code Online (Sandbox Code Playgroud)

我曾尝试:我已经尝试了许多张贴的解决方案,因此,在这个问题,因为它涉及到iOS 7,所有这一切我已经尝试做解决方案的似乎保持良好的显示属性串文本视图.在以下三个步骤中,我概述了SO(/sf/answers/1349416841/)上最多投票的答案如何响应用户第一次点击返回键.

(1.)文本视图成为第一个响应者viewDidLoad.滚动到光标所在文本视图的底部.

在此输入图像描述

(2.)在键入单个字符之前,请点击键盘上的返回键.插入符号消失在视线之外.

在此输入图像描述

(3)然而,再次点击返回键似乎使情况正常化.(注意:删除后一个新行会使插入符号再次消失).

在此输入图像描述

Dmi*_*try 11

改进了UITextView后代类的解决方案代码:

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define is_iOS7 SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")
#define is_iOS8 SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")

@implementation MyTextView {
    BOOL settingText;
}

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTextViewDidChangeNotification:) name:UITextViewTextDidChangeNotification object:self];
    }
    return self;
}

- (void)scrollToCaretInTextView:(UITextView *)textView animated:(BOOL)animated {
    CGRect rect = [textView caretRectForPosition:textView.selectedTextRange.end];
    rect.size.height += textView.textContainerInset.bottom;
    [textView scrollRectToVisible:rect animated:animated];
}

- (void)handleTextViewDidChangeNotification:(NSNotification *)notification {
    if (notification.object == self && is_iOS7 && !is_iOS8 && !settingText) {
        UITextView *textView = self;
        if ([textView.text hasSuffix:@"\n"]) {
            [CATransaction setCompletionBlock:^{
                [self scrollToCaretInTextView:textView animated:NO];
            }];
        } else {
            [self scrollToCaretInTextView:textView animated:NO];
        }
    }
}

- (void)setText:(NSString *)text {
    settingText = YES;
    [super setText:text];
    settingText = NO;
}
Run Code Online (Sandbox Code Playgroud)

请注意,在蓝牙键盘上按下向下键时,它不起作用.


bil*_*tum 9

在以下情况下,应该采用强有力的解决方案:

(1.)显示属性字符串的文本视图

(2.)通过点击键盘上的返回键创建的新行

(3.)通过键入溢出到下一行的文本创建的新行

(4.)复制并粘贴文本

(5)第一次点击返回键创建的新行(参见OP中的3个步骤)

(6.)设备旋转

(7.)有些情况我想不到你会......

为了满足iOS 7.1中的这些要求,似乎仍然需要手动滚动到插入符号.

在调用文本视图委托方法textViewDidChange:时,通常会看到手动滚动到插入符的解决方案.但是,我发现这种技术不能满足上面的情况#5.即使layoutIfNeeded在滚动到插入符号之前调用也无济于事.相反,我不得不滚动到CATransaction完成块内的插入符号:

// this seems to satisfy all of the requirements listed above–if you are targeting iOS 7.1
- (void)textViewDidChange:(UITextView *)textView
{
    if ([textView.text hasSuffix:@"\n"]) {

        [CATransaction setCompletionBlock:^{
            [self scrollToCaretInTextView:textView animated:NO];
        }];

    } else {
        [self scrollToCaretInTextView:textView animated:NO];
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么这样做?我不知道.你将不得不问一位Apple工程师.

为了完整起见,这里是与我的解决方案相关的所有代码:

#import "ViewController.h"

@interface ViewController () <UITextViewDelegate>

@property (weak, nonatomic) IBOutlet UITextView *textView; // full-screen

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *string = @"All work and no play makes Jack a dull boy.\n\nAll work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy.";

    NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:string attributes:@{NSFontAttributeName: [UIFont fontWithName:@"Verdana" size:30.0]}];

    self.textView.attributedText = attrString;

    self.textView.delegate = self;
    self.textView.backgroundColor = [UIColor yellowColor];
    [self.textView becomeFirstResponder];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardIsUp:) name:UIKeyboardDidShowNotification object:nil];
}

// helper method
- (void)scrollToCaretInTextView:(UITextView *)textView animated:(BOOL)animated
{
    CGRect rect = [textView caretRectForPosition:textView.selectedTextRange.end];
    rect.size.height += textView.textContainerInset.bottom;
    [textView scrollRectToVisible:rect animated:animated];
}

- (void)keyboardIsUp:(NSNotification *)notification
{
    NSDictionary *info = [notification userInfo];
    CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

    UIEdgeInsets inset = self.textView.contentInset;
    inset.bottom = keyboardRect.size.height;
    self.textView.contentInset = inset;
    self.textView.scrollIndicatorInsets = inset;

    [self scrollToCaretInTextView:self.textView animated:YES];
}

- (void)textViewDidChange:(UITextView *)textView
{
    if ([textView.text hasSuffix:@"\n"]) {

        [CATransaction setCompletionBlock:^{
            [self scrollToCaretInTextView:textView animated:NO];
        }];

    } else {
        [self scrollToCaretInTextView:textView animated:NO];
    }
}

@end
Run Code Online (Sandbox Code Playgroud)

如果您发现这种情况不起作用,请告诉我.