UITextView 在打字时隐藏文本

发布于 2024-10-19 15:34:03 字数 2596 浏览 0 评论 0原文

我看到一些非常奇怪的行为。我有一个文本视图显示在作为滚动视图一部分的视图内。如果当我开始在文本视图中键入内容时,键盘通常会隐藏该文本视图,然后我为文本视图设置动画并将其推到键盘上方以使其保持可见。如果我这样做,我键入的第三行和后续行将不可见,直到我关闭键盘,此时我才能看到我键入的文本。如果,当我开始在文本视图中输入时,我不需要将其动画化以将其向上推(因为键盘不会隐藏它),那么我可以看到我输入的所有文本,因此我的问题仅在文本时出现视图是动画的。

下面是我创建文本视图的代码:

    self.textView = [[UITextView alloc] initWithFrame:CGRectMake(...)];
    textView.font = [UIFont systemFontOfSize:18.0];
    textView.backgroundColor = [UIColor whiteColor];
    textView.userInteractionEnabled = YES;
    textView.clipsToBounds = YES;
    textView.delegate = self;
    textView.layer.borderWidth = 1; 
    textView.layer.borderColor = [[UIColor blackColor] CGColor];
    textView.layer.cornerRadius = 10;
    [self addSubview:textView];
    [textView release];

下面是为文本视图设置动画的代码:

- (void) makeTextViewVisible: (UITextView *)textArea up:(BOOL) up {

if (up) {
    animatedDistance = 0;

    CGPoint myPoint = [textArea.superview convertPoint:textArea.frame.origin toView:[UIApplication sharedApplication].keyWindow];

    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    if (orientation == UIInterfaceOrientationPortrait) {
        animatedDistance = PORTRAIT_KEYBOARD_HEIGHT - (950 - myPoint.y) + 150;
    }
    else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
        animatedDistance = PORTRAIT_KEYBOARD_HEIGHT + (PORTRAIT_KEYBOARD_HEIGHT - myPoint.y);   
    }
    else if (orientation == UIInterfaceOrientationLandscapeLeft) {
        animatedDistance = myPoint.x - LANDSCAPE_KEYBOARD_HEIGHT + 120;
    }
    else if (orientation == UIInterfaceOrientationLandscapeRight) {
        animatedDistance = LANDSCAPE_KEYBOARD_HEIGHT - myPoint.x + 100; 
    }

    if (animatedDistance < 0) {
        animatedDistance = 0.0; 
    }

    CGRect viewFrame = textArea.frame;
    viewFrame.origin.y -= animatedDistance;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

    [textArea setFrame:viewFrame];

    [UIView commitAnimations];

} 
else {
    CGRect viewFrame = textArea.frame;
    viewFrame.origin.y += animatedDistance;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

    [textArea setFrame:viewFrame];

    [UIView commitAnimations];      
}

我尝试在 textViewDidChange 内调用 setNeedsDisplay/setNeedsLayout,但没有成功。

有人以前遇到过这个问题,或者知道如何解决吗?

谢谢!

I see some very strange behavior. I have a text view displayed inside a view which is part of a scroll view. If when I start typing in the text view, the keyboard would normally hide that text view, then I animate the text view and push it above the keyboard so that it stays visible. If I do that, the third and subsequent rows that I type are not visible until I dismiss the keyboard at which moment I can see the text I typed. If, when I start typing in the text view, I don't need to animate it to push it up (because the keyboard does not hides it), then I can see all the text I type, hence my problem only arises when text view is animated.

Below is my code that creates the text view:

    self.textView = [[UITextView alloc] initWithFrame:CGRectMake(...)];
    textView.font = [UIFont systemFontOfSize:18.0];
    textView.backgroundColor = [UIColor whiteColor];
    textView.userInteractionEnabled = YES;
    textView.clipsToBounds = YES;
    textView.delegate = self;
    textView.layer.borderWidth = 1; 
    textView.layer.borderColor = [[UIColor blackColor] CGColor];
    textView.layer.cornerRadius = 10;
    [self addSubview:textView];
    [textView release];

Below is the code that animates the text view:

- (void) makeTextViewVisible: (UITextView *)textArea up:(BOOL) up {

if (up) {
    animatedDistance = 0;

    CGPoint myPoint = [textArea.superview convertPoint:textArea.frame.origin toView:[UIApplication sharedApplication].keyWindow];

    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    if (orientation == UIInterfaceOrientationPortrait) {
        animatedDistance = PORTRAIT_KEYBOARD_HEIGHT - (950 - myPoint.y) + 150;
    }
    else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
        animatedDistance = PORTRAIT_KEYBOARD_HEIGHT + (PORTRAIT_KEYBOARD_HEIGHT - myPoint.y);   
    }
    else if (orientation == UIInterfaceOrientationLandscapeLeft) {
        animatedDistance = myPoint.x - LANDSCAPE_KEYBOARD_HEIGHT + 120;
    }
    else if (orientation == UIInterfaceOrientationLandscapeRight) {
        animatedDistance = LANDSCAPE_KEYBOARD_HEIGHT - myPoint.x + 100; 
    }

    if (animatedDistance < 0) {
        animatedDistance = 0.0; 
    }

    CGRect viewFrame = textArea.frame;
    viewFrame.origin.y -= animatedDistance;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

    [textArea setFrame:viewFrame];

    [UIView commitAnimations];

} 
else {
    CGRect viewFrame = textArea.frame;
    viewFrame.origin.y += animatedDistance;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

    [textArea setFrame:viewFrame];

    [UIView commitAnimations];      
}

I tried calling setNeedsDisplay/setNeedsLayout inside textViewDidChange, but with no luck.

Anybody encountered this problem before, or know how to solve it?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小瓶盖 2024-10-26 15:34:03

给你一些想法。首先,我认为你在动画距离计算上工作得太辛苦了。我通常创建一个主视图,而不是使用 UIWindow 的尺寸(不随设备旋转)。否则,正如您所发现的,您必须考虑状态栏、手机状态栏等。使用视图可以将所有这些计算减少到一个(仅补偿两个不同的键盘高度):

if ((orientation == UIInterfaceOrientationLandscapeLeft)|| (orientation == UIInterfaceOrientationLandscapeRight)) {
    keyboardHeight = LANDSCAPE_KEYBOARD_HEIGHT;
} else {
    keyBoardHeight = PORTRAIT_KEYBOARD_HEIGHT; 
}

CGPoint myPoint = [self.view convertPoint:textArea.frame.origin toView:self.view];
float windowHeight = self.view.bounds.size.height;

animatedDistance = myPoint.y+textArea.bounds.size.height+keyboardHeight-windowHeight;   

if (animatedDistance < 0) {
    animatedDistance = 0.0; 
}

所以使用视图的边界可以获取所需的信息。

其次,为什么要移动textView?为什么不直接调整滚动窗口的scrollPos呢?

第三,您引用的 textView 位于滚动视图内的视图内(尽管我在代码中没有看到这一点)。您的 textView 可能被中间视图的边界剪切,这将导致能够在其中输入内容,但无法看到结果。你能看到你的textView的边界吗?

最后,从美学角度来看,animatedDistance 是一个状态变量,在放回动画后,您应该在 else 分支中将animatedDistance 设置为零。这样,如果您出于某种原因调用 makeTextViewVisible:textView UP:false 两次,它不会让您陷入困境。

A couple of thoughts for you. First, I think you're working too hard with the animatedDistance calculation. I usually create a master view rather than working with the UIWindow's dimensions (which don't rotate with the device). Otherwise, as you've discovered, you have to take into consideration the status bar, the phone status bar, etc. Using the view allows you to reduce all those calculations down to one (just compensating for the two different keyboard heights):

if ((orientation == UIInterfaceOrientationLandscapeLeft)|| (orientation == UIInterfaceOrientationLandscapeRight)) {
    keyboardHeight = LANDSCAPE_KEYBOARD_HEIGHT;
} else {
    keyBoardHeight = PORTRAIT_KEYBOARD_HEIGHT; 
}

CGPoint myPoint = [self.view convertPoint:textArea.frame.origin toView:self.view];
float windowHeight = self.view.bounds.size.height;

animatedDistance = myPoint.y+textArea.bounds.size.height+keyboardHeight-windowHeight;   

if (animatedDistance < 0) {
    animatedDistance = 0.0; 
}

So using the view's bounds gets you the info you need.

Secondly, why move the textView? Why not just adjust the scrollPos of your scroll window?

Third, you refer to the textView being inside a view which is inside a scrollview (although I don't see that in the code). It's possible your textView is being clipped by the middle view's boundaries, which would lead to being able to type in it, but not being able to see the results. Can you see the boundaries of your textView?

Finally, as an aesthetic point, animatedDistance is a state variable, you should set animatedDistance to zero in your else branch after you've put the animation back. That way, if you call makeTextViewVisible:textView UP:false twice for some reason, it won't mess you up.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文