我正在使用UITextView粗略复制键盘上方的SMS文本框。我正在使用UITextView而不是字段,因此它可以使用多行进行扩展。
问题是,在我的UITextView中,更正建议会在文本下方 下方显示,导致它们被键盘部分遮挡。
在短信应用中,建议会在文本上方弹出。该展示位置似乎不是UITextView或UITextInputTraits的属性。
知道如何复制这种行为吗?谢谢!
答案 0 :(得分:8)
问题在于,键盘是作为单独的UIWindow实现的,而不是作为主UIWindow中的视图实现的,因此使用它进行布局非常棘手。以下是正确方向的一些指示:
-windows
属性以查找私有UITextEffectsWindow
窗口并找出其框架。这是键盘UIAutocorrectInlinePrompt
视图。这是自动更正泡沫。你会注意到上面提到的两个“私人”。这带来了所有相关的警告。我不知道为什么Apple甚至在他们的应用程序不得不解决它时仍然允许问题持续存在。
答案 1 :(得分:3)
通过在重写或调配的layoutSubViews中搜索UIAutocorrectInlinePrompt,可以更改校正的布局,使其显示在上方。您可以在不调用任何私有API的情况下执行此操作,方法是查找以您期望的方式放置的特定类的子视图。这个例子确定哪个视图是哪个视图,检查校正是否已经在文本上方并移动上面的校正,并在窗口上绘制它,使其不受UITextView本身的限制。显然,如果苹果改变了底层实施,那么这将无法进行修正。将其添加到您的覆盖或混合layoutSubViews实现中。
- (void) moveSpellingCorrection {
for (UIView *view in self.subviews)
{
if ([[[view class] description] isEqualToString:@"UIAutocorrectInlinePrompt"])
{
UIView *correctionShadowView = nil; // [view correctionShadowView];
for (UIView *subview in view.subviews)
{
if ([[[subview class] description] isEqualToString:@"UIAutocorrectShadowView"])
{
correctionShadowView = subview;
break;
}
}
if (correctionShadowView)
{
UIView *typedTextView = nil; //[view typedTextView];
UIView *correctionView = nil; //[view correctionView];
for (UIView *subview in view.subviews)
{
if ([[[subview class] description] isEqualToString:@"UIAutocorrectTextView"])
{
if (CGRectContainsRect(correctionShadowView.frame,subview.frame))
{
correctionView = subview;
}
else
{
typedTextView = subview;
}
}
}
if (correctionView && typedTextView)
{
CGRect textRect = [typedTextView frame];
CGRect correctionRect = [correctionView frame];
if (textRect.origin.y < correctionRect.origin.y)
{
CGAffineTransform moveUp = CGAffineTransformMakeTranslation(0,-50.0);
[correctionView setTransform: moveUp];
[correctionShadowView setTransform: moveUp];
CGRect windowPos = [self convertRect: view.frame toView: nil ];
[view removeFromSuperview];
[self.window addSubview: view];
view.frame = windowPos;
}
}
}
}
}
}
答案 2 :(得分:1)
实际上在做
textview.scrollEnabled = NO;
会将泡泡设置在文本的顶部...需要注意的是,您丢失了滚动条件,在我的情况下,由于仅仅出于字符限制的输入目的而使用文本字段而不是问题
答案 3 :(得分:1)
实际上,键盘只使用 - [UITextInput textInputView]的结果来确定放置校正视图的位置(并询问您的视图是否支持校正)。所以你需要做的就是:
- (UIView *)textInputView {
for (UIWindow *window in [UIApplication sharedApplication].windows) {
if ([window isKindOfClass:NSClassFromString(@"UITextEffectsWindow")] &&
window != self.window) {
return window;
}
}
// Fallback just in case the UITextEffectsWindow has not yet been created.
return self;
}
请注意,您可能还需要更新 - [UITextInput firstRectForRange:]以使用窗口/设备的坐标系,因此您可以执行此操作:
- (CGRect)firstRectForRange:(CoreTextTokenTextRange *)range {
CGRect firstRect = [self firstRectForRangeInternal:range];
return [self convertRect:firstRect toView:[self textInputView]];
}
(在上面的上下文中,self是一个实现UITextInput的类。)
答案 4 :(得分:0)
如果UITextView的底部清除了键盘,您应该只需调整UITextView的大小就足以看到更正。更正本身不会显示在UITextView框架之外。
如果你想模仿你在短信应用程序中获得的内容(上面的更正),你可能需要自己动手。
答案 5 :(得分:0)
使用下面的方法,layoutSubviews中的adjustAutocorrectPromptView在纵向和横向上为我工作。我有一个类别,提供了视图的底部和顶部方法,但你明白了。
NSArray * subviewsWithDescription(UIView *view, NSString *description)
{
return [view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"class.description == '%@'", description]]];
}
- (void) adjustAutocorrectPromptView;
{
UIView *autocorrectPromptView = [subviewsWithDescription(self, @"UIAutocorrectInlinePrompt") lastObject];
if (! autocorrectPromptView)
{
return;
}
UIView *correctionShadowView = [subviewsWithDescription(autocorrectPromptView, @"UIAutocorrectShadowView") lastObject];
if (! correctionShadowView)
{
return;
}
UIView *typedTextView = nil; //[view typedTextView];
UIView *correctionView = nil; //[view correctionView];
for (UIView *subview in subviewsWithDescription(autocorrectPromptView, @"UIAutocorrectTextView"))
{
if (CGRectContainsRect(correctionShadowView.frame,subview.frame))
{
correctionView = subview;
}
else
{
typedTextView = subview;
}
}
if (correctionView && typedTextView)
{
if (typedTextView.top < correctionView.top)
{
correctionView.bottom = typedTextView.top;
correctionShadowView.center = correctionView.center;
}
}
}
答案 6 :(得分:-2)
确保您的视图控制器委托在弹出键盘时正在收听通知,以便您调整UITextView的大小,以便键盘不会遮盖UITextView。然后键盘不会遮挡你的修正。参见:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/12641-uitextview-scroll-while-editing.html
以下是原始链接断开时该页面代码的副本:
// the amount of vertical shift upwards keep the Notes text view visible as the keyboard appears
#define kOFFSET_FOR_KEYBOARD 140.0
// the duration of the animation for the view shift
#define kVerticalOffsetAnimationDuration 0.50
- (IBAction)textFieldDoneEditing:(id)sender
{
[sender resignFirstResponder];
}
- (IBAction)backgroundClick:(id)sender
{
[latitudeField resignFirstResponder];
[longitudeField resignFirstResponder];
[notesField resignFirstResponder];
if (viewShifted)
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:kVerticalOffsetAnimationDuration];
CGRect rect = self.view.frame;
rect.origin.y += kOFFSET_FOR_KEYBOARD;
rect.size.height -= kOFFSET_FOR_KEYBOARD;
self.view.frame = rect;
[UIView commitAnimations];
viewShifted = FALSE;
}
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
if (!viewShifted) { // don't shift if it's already shifted
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:kVerticalOffsetAnimationDuration];
CGRect rect = self.view.frame;
rect.origin.y -= kOFFSET_FOR_KEYBOARD;
rect.size.height += kOFFSET_FOR_KEYBOARD;
self.view.frame = rect;
[UIView commitAnimations];
viewShifted = TRUE;
}
return YES;
}