我有一个UITextView坐在UIView的顶部,如果我点击它打开它进行编辑,那么键盘会阻挡视图的底部,即使我可以在这个区域写入,我也看不到它。我可以告诉UITextView有不同的滚动区域或解决方案是什么?
答案 0 :(得分:30)
一个更好的解决方案,特别是针对iOS 7,将调整textview的内容插入属性而不是其框架,这样,键盘将模糊落后的文本,就像在任何其他iOS 7应用程序中一样。您还必须调整滚动指示符以匹配。
扩大林德曼的答案,
- (void)keyboardWasShown:(NSNotification*)notification {
NSDictionary* info = [notification userInfo];
CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
self.textView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0);
self.textView.scrollIndicatorInsets = self.textView.contentInset;
}
- (void)keyboardWillBeHidden:(NSNotification*)notification {
self.textView.contentInset = UIEdgeInsetsZero;
self.textView.scrollIndicatorInsets = UIEdgeInsetsZero;
}
答案 1 :(得分:14)
一个简单的解决方案是实现UITextViewDelegate
方法
- (void)textViewDidBeginEditing:(UITextView *)textView
和
- (void)textViewDidEndEditing:(UITextView *)textView
当键盘出现时,您可以将UITextView框架缩小,并在键盘消失时再次将其设置为完整尺寸...如下所示:
- (void)textViewDidBeginEditing:(UITextView *)textView {
self.textView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height/1.8);
}
- (void)textViewDidEndEditing:(UITextView *)textView {
self.textView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}
修改强>
上面的解决方案很糟糕......不要使用!!!
现在我认为按照键盘大小而不是固定值来调整UITextView的大小更好...因为当选择其他语言或设备旋转时键盘的大小会发生变化。 。当然 - .-
首先,您必须注册UIViewController
,以显示您的UITextView
以接收键盘通知:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
然后你必须实现两个方法-keyboardWasShown:
和
-keyboardWillBeHidden:
。
实际键盘的大小包含在NSNotification
对象中。
- (void)keyboardWasShown:(NSNotification*)notification {
NSDictionary* info = [notification userInfo];
CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
self.textView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - keyboardSize.height);
}
- (void)keyboardWillBeHidden:(NSNotification*)notification {
self.textView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}
答案 2 :(得分:5)
如果您想要消息应用程序样式输入,可以使用嵌套的UITextView(允许多行文本)。它最终会是这样的:
首先布置一个视图来保存所有子视图。这里bottomView的背景颜色设置为与UIKeyboardAppearanceDark匹配。它位于屏幕的底部。
bottomView = [UIView new];
bottomView.frame = CGRectMake(0, h-45, w, 45);
bottomView.backgroundColor = [UIColor colorWithRed:0.078 green:0.078 blue:0.078 alpha:1];
[self.view addSubview:bottomView];
然后,添加一个简单的背景视图,其样式类似于典型的UITextField,并将UITextView作为子视图添加到其中。 inputTV(UITextView)根据字体大小获取其高度。此外,使用textContainer变量从inputTV中删除所有填充。
inputTVBG = [UIImageView new];
inputTVBG.frame = CGRectMake(10, 8, w-90, 29);
inputTVBG.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.1f];
inputTVBG.layer.cornerRadius = 4.0f;
inputTVBG.userInteractionEnabled = true;
inputTVBG.clipsToBounds = true;
[bottomView addSubview:inputTVBG];
inputTV = [UITextView new];
inputTV.font = [UIFont systemFontOfSize:14.0f];
inputTV.frame = CGRectMake(5, 6, w-100, inputTV.font.lineHeight);
inputTV.backgroundColor = [UIColor clearColor];
inputTV.keyboardAppearance = UIKeyboardAppearanceDark;
inputTV.delegate = self;
inputTV.autocorrectionType = UITextAutocorrectionTypeNo;
inputTV.tintColor = [UIColor whiteColor];
inputTV.textColor = [UIColor whiteColor];
inputTV.textContainer.lineFragmentPadding = 0;
inputTV.textContainerInset = UIEdgeInsetsZero;
[inputTVBG addSubview:inputTV];
在上面的示例中,我提供了一个标签,指示剩余的字母数(最大/最小字符数)和提交按钮。
lettersLeftLabel = [UILabel new];
lettersLeftLabel.frame = CGRectMake(w-70, 8, 60, 16);
lettersLeftLabel.font = [UIFont systemFontOfSize:12.0f];
lettersLeftLabel.textColor = [[UIColor whiteColor] colorWithAlphaComponent:0.5f];
lettersLeftLabel.alpha = 0.0f;
[bottomView addSubview:lettersLeftLabel];
submitButton = [UIButton new];
submitButton.frame = CGRectMake(w-70, 0, 60, 45);
[submitButton setTitle:@"SUBMIT" forState:UIControlStateNormal];
[submitButton setTitleColor:[_peacock.applePink colorWithAlphaComponent:0.5f] forState:UIControlStateNormal];
[submitButton addTarget:self action:@selector(submit) forControlEvents:UIControlEventTouchUpInside];
[submitButton.titleLabel setFont:[UIFont boldSystemFontOfSize:14.0f]];
[bottomView addSubview:submitButton];
在代码的早期添加此行,以便获得键盘更改更新:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
当用户点击inputTV时,它会调用以下方法。在这里它设置变量&keyboard;标注'稍后使用。
-(void)keyboardWillShow:(NSNotification *)n {
CGRect rect = [n.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardFrame = [self.view convertRect:rect fromView:nil];
keyboardHeight = keyboardFrame.size.height;
[self textViewDidChange:inputTV];
}
这是代码的主要部分,负责处理输入电视的所有移动和调整大小。
-(void)textViewDidChange:(UITextView *)textView {
//1. letters and submit button vars
int numberOfCharacters = (int)textView.text.length;
int minCharacters = 50;
int maxCharacters = 400;
int remainingCharacters = maxCharacters-numberOfCharacters;
//2. if entered letters exceeds maximum, reset text and return
if (remainingCharacters <= 0){
textView.text = [textView.text substringToIndex:maxCharacters];
numberOfCharacters = maxCharacters;
}
//3. set height vars
inputTV.scrollEnabled = true;
float textHeight = textView.contentSize.height;
float lineHeight = roundf(textView.font.lineHeight);
float additionalHeight = textHeight - lineHeight;
float moveUpHeight = keyboardHeight + additionalHeight;
//4. default letter colour is weak white
UIColor * letterColour = [[UIColor whiteColor] colorWithAlphaComponent:0.5f];
if (numberOfCharacters < minCharacters){ //minimum threshold not met
lettersLeftLabel.text = [NSString stringWithFormat:@"%i", minCharacters-numberOfCharacters];
letterColour = [_peacock.applePink colorWithAlphaComponent:0.5f];
} else { //within range
lettersLeftLabel.text = [NSString stringWithFormat:@"%i/%i", numberOfCharacters, maxCharacters];
if (remainingCharacters<5){ //increase alpha towards the end of range
letterColour = [[UIColor whiteColor] colorWithAlphaComponent:1.0f - ((float)remainingCharacters/10)];
}
}
//5. hide/show letter label based on textView height
float letterAlpha = 0.0f; //default hide
if (additionalHeight > 0){ letterAlpha = 1.0f; } //if multiline, show
[UIView animateWithDuration:0.3f
delay:0.0f
options:UIViewAnimationOptionCurveEaseOut
animations:^{
lettersLeftLabel.alpha = letterAlpha;
lettersLeftLabel.textColor = letterColour;
}
completion:^(BOOL finished){
}];
//6. update submit colour based on minimum threshold
UIColor * submitColour = [_peacock.applePink colorWithAlphaComponent:0.5f];
bool enableSubmit = false;
if (numberOfCharacters >= minCharacters){
submitColour = _peacock.applePink;
enableSubmit = true;
}
[submitButton setEnabled:enableSubmit];
[UIView animateWithDuration:0.3f
delay:0.0f
options:UIViewAnimationOptionCurveEaseOut
animations:^{
[submitButton setTitleColor:submitColour forState:UIControlStateNormal];
}
completion:^(BOOL finished){
}];
//7. special case if you want to limit the frame size of the input TV to a specific number of lines
bool shouldEnableScroll = false;
int maxNumberOfLines = 5; //anything above this triggers the input TV to stay stationary and update its scroll
int actualNumberOfLines = textHeight / textView.font.lineHeight;
if (actualNumberOfLines >= maxNumberOfLines){ //recalculate vars for frames
textHeight = maxNumberOfLines * lineHeight;
additionalHeight = textHeight - lineHeight;
moveUpHeight = keyboardHeight + additionalHeight;
shouldEnableScroll = true;
}
//8. adjust frames of views
inputTV.frame = CGRectMake(5, 6, w-100, textHeight); //update immediately (parent view clips to bounds)
[UIView animateWithDuration:0.3f
delay:0.0f
options:UIViewAnimationOptionCurveEaseOut
animations:^{
bottomView.frame = CGRectMake(0, h-45-moveUpHeight, w, 45+additionalHeight);
inputTVBG.frame = CGRectMake(10, 8, w-90, lineHeight+additionalHeight+13);
submitButton.frame = CGRectMake(w-70, additionalHeight, 60, 45);
}
completion:^(BOOL finished){
inputTV.scrollEnabled = shouldEnableScroll; //default disable scroll here to avoid bouncing
}];
}
在上述方法中,这就是发生的事情:
如果要设置最小或最大字符数,可以在此处执行此操作。您拉出字符数并存储为整数,并计算剩余的字符数。
如果用户已达到最大字符数,请通过剥离回到最大值来重置textView文本。
这些变量用于计算移动bottomView以及调整其子视图所需的量。
此方法仅用于更改某些UI元素的颜色/文本。这不是绝对必要的。
如果你正在使用它,这个方法会将lettersLeftLabel带到视图上。它也没有必要。
仅在达到最小字符数时才启用提交按钮。它将颜色更改为用户的指示。
如果要限制inputTV和周围元素的增长,可以包含这段代码。它要求您设置要显示的最大行数。如果用户超过最大值,则为inputTV重新启用滚动,否则默认为false(重要的是停止弹跳)。
这是主要的调整大小逻辑,将bottomView向上移动并调整其子视图的大小。提交按钮需要保持在相同的位置,因此随着bottomView的增长将其向下移动。
注意:如果您只想要准系统代码,则只需执行步骤3和8.
答案 3 :(得分:4)
Apple有一些code samples处理这种情况。
答案 4 :(得分:4)
我终于开始工作了。这是我的解决方案,你们可以发现我设计中的任何错误吗?
@synthesize textView = _textView;
@synthesize callbackViewController = _callbackViewController;
-(void)keyboardWasShown:(NSNotification*)aNotification {
if(keyboardShown) {
return;
}
NSDictionary *info = [aNotification userInfo];
// Get the size of the keyboard.
NSValue *aValue = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];
keyboardSize = [aValue CGRectValue].size;
// Resize the scroll view (which is the root view of the window)
CGRect viewFrame = [self.textView frame];
orientationAtShown = orientation;
if(orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
viewFrame.size.height -= keyboardSize.height;
} else {
viewFrame.size.height -= keyboardSize.width;
}
self.textView.frame = viewFrame;
// Scroll the active text field into view.
//CGRect textFieldRect = [activeField frame];
[self.textView scrollRectToVisible:viewFrame animated:YES];
keyboardShown = YES;
}
-(void)keyboardWasHidden:(NSNotification*)aNotification {
if(!keyboardShown) {
return;
}
// Reset the height of the scroll view to its original value
CGRect viewFrame = [self.textView frame];
if(orientationAtShown == UIInterfaceOrientationPortrait || orientationAtShown == UIInterfaceOrientationPortraitUpsideDown) {
viewFrame.size.height += keyboardSize.height;
} else {
viewFrame.size.height += keyboardSize.width;
}
self.textView.frame = viewFrame;
keyboardShown = NO;
}
-(void)registerForKeyboardNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification object:nil];
}
-(void)viewWillAppear:(BOOL)animated {
keyboardShown = NO;
[self registerForKeyboardNotifications];
}
-(void)viewWillDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if(keyboardShown) {
[self keyboardWasHidden:nil];
}
orientation = interfaceOrientation;
CGRect viewFrame = [self.textView frame];
if(orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
if(viewFrame.size.width > viewFrame.size.height) {
CGRect viewFrameFixed = CGRectMake(viewFrame.origin.x, viewFrame.origin.y, viewFrame.size.height, viewFrame.size.width);
self.textView.frame = viewFrameFixed;
}
} else {
if(viewFrame.size.width < viewFrame.size.height) {
CGRect viewFrameFixed = CGRectMake(viewFrame.origin.x, viewFrame.origin.y, viewFrame.size.height, viewFrame.size.width);
self.textView.frame = viewFrameFixed;
}
}
// Return YES for supported orientations
return YES;
}
答案 5 :(得分:4)
@Alejandro上面有正确的想法,但他的代码在横向模式下不起作用。我修改了他的keyboardWasShown:
方法,以便在所有方向上正确运行:
- (void)keyboardWasShown:(NSNotification *)notification {
if (self.textView != nil) {
NSDictionary* info = [notification userInfo];
CGRect keyboardRect = [self.textView convertRect:[[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] fromView:nil];
CGSize keyboardSize = keyboardRect.size;
self.textView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0);
self.textView.scrollIndicatorInsets = self.textView.contentInset;
}
}
答案 6 :(得分:2)
首先在viewDidLoad
中添加观察者。
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
调用方法
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
self.textView.contentInset = contentInsets;
self.textView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your app might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, self.textView.frame.origin) ) {
[self.textView scrollRectToVisible:self.textView.frame animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWasHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.textView.contentInset = contentInsets;
self.textView.scrollIndicatorInsets = contentInsets;
}
答案 7 :(得分:1)
如果您有超过1个文本字段,或者想要减少代码,请尝试使用此代码
- (void)textFieldDidBeginEditing:(UITextField *)textField{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frame = self.view.frame;
frame.origin.y = (self.view.frame.size.height - textField.frame.origin.y) - self.view.frame.size.height+60;
if (frame.origin.y<-162) {
frame.origin.y = -162;
}
[self.view setFrame:frame];
[UIView commitAnimations];
}
-(BOOL)textFieldShouldEndEditing:(UITextField *)textField{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frame = self.view.frame;
frame.origin.y = 0;
[self.view setFrame:frame];
[UIView commitAnimations];
return YES;
}
答案 8 :(得分:0)
扩展@alejandro&amp; @Mani:
最终答案:
- (void)keyboardWasShown:(NSNotification *)notification {
if (self.textView != nil) {
NSDictionary* info = [notification userInfo];
CGRect keyboardRect = [self.textNote convertRect:[[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] fromView:nil];
CGSize keyboardSize = keyboardRect.size;
self.textView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0);
self.textView.scrollIndicatorInsets = self.textView.contentInset;
}
}
- (void)keyboardWillBeHidden:(NSNotification*)notification {
self.textView.scrollIndicatorInsets = UIEdgeInsetsZero;
self.textView.scrollIndicatorInsets = UIEdgeInsetsZero;
}