我在UITextView
中的textView之后和之后有UIScrollView
和其他观点。
当用户输入文本时,我在textView.contentSize.height上更改textView框架高度。
这个想法是节省用户查看所有文本和其他元素的可能性。
我有一些问题。当用户点击我想滚动到这一行。这看起来似乎是:
我无法确定如何计算偏移量并始终滚动到当前的插入符号。
我的初始屏幕:
所有观看次数均为UIScrollView
的子视图。
每当用户输入@"\n"
时,我都会更改UITextView
框架:
CGRect textViewFrame = textView.frame;
CGSize textViewContentSize = textView.contentSize;
NSLog(@"textView content size: %@", NSStringFromCGSize(textViewContentSize));
textViewFrame.size.height = textViewContentSize.height;
[textView setFrame:textViewFrame];
我增加UIScrollView
contentSize。
我的问题 - 我不明白如何在键盘下滚动到textView的 CURSOR 。
我尝试做点什么:
CGPoint cursorPosition = [textView caretRectForPosition:textView.selectedTextRange.start].origin;
CGPoint relativeCursorPoint = [textView convertPoint:cursorPosition toView:scrollView];
if(textView.isFirstResponder && relativeCursorPoint.y >= scrollViewFrame.size.height + scrollView.contentOffset.y)
{
int offset = relativeCursorPoint.y - scrollViewFrame.size.height + 18.0f;
//int offset = textViewRect.origin.y - scrollViewFrame.size.height + 18.0f;
[scrollView setContentOffset:CGPointMake(0, offset) animated:YES];
}
但它不起作用。
答案 0 :(得分:1)
A。)为了达到与Apple Notes滚动+键盘解雇类似的效果,我首先在UIScrollView中添加了一个UITextView。
B。)然后添加self作为键盘更改的观察者:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewDidBeginEditing:) name:UITextViewTextDidBeginEditingNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
C。)然后当用户点击textview / textfield时,调用下面的方法。您获取键盘的起始高度和结束高度,并将名为keyboardHeight的变量设置为endHeight值(稍后使用)。
下面计算的“差异”用于在用户上下移动自动更正/建议栏时上下移动文本。如果您不想这样,可以将textView上的'autocorrectionType'设置为false。
-(void)keyboardWillChangeFrame:(NSNotification *)n {
float beginHeight = [[n.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height;
float endHeight = [[n.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
float difference = beginHeight-endHeight;
keyBoardHeight = endHeight; //set the var
//animate change
if (difference != 0){ //animate frame change in your textview }
}
D。)在textViewDidBegin方法上,将UIScrollview移动到屏幕顶部,因此textview与top(setContentOffset)齐平。
您可以计算文本视图的高度,因为它应该位于视图顶部和键盘顶部之间,在下面称为“initialTVHeight”。
你应该强制textview启用它的滚动,所以将textView.contentSize设置为最小尺寸(initialTVHeight)+一个像素 - 这会强制滚动。
-(void)textViewDidBeginEditing:(UITextView *)textView {
//need to move the tv up to the top
float yOff = 0;
yOff += durationCell.frame.size.height;
yOff += reminderCell.frame.size.height;
yOff += fixedCell.frame.size.height;
yOff += repeatCell.frame.size.height;
[mainScroller setContentOffset:CGPointMake(0, yOff) animated:true];
//resize the textview to meet the top of the keyboard
float padding = 0; //padding between keyboard and last line in the textview
initialTVHeight = h - 60 - keyBoardHeight - padding; //the height when text does not overflow
textTV.frame = CGRectMake(0, textTV.frame.origin.y, w, initialTVHeight); //set the frame to that size
//if smaller than minimum, increase (if editing existing text)
if (textTV.contentSize.height < initialTVHeight){
textTV.contentSize = CGSizeMake(w, initialTVHeight+1); //force initial scroll
}
}
E。)此方法将textView contentSize更新为最小高度以确保启用滚动(即,如果只有两行文本,则用户仍可以反弹滚动)。 textView内容长于初始大小的地方,允许它自然增长。
-(void)textViewDidChange:(UITextView *)textView {
//require minimum height for scroll
if (textTV.contentSize.height < initialTVHeight){ //content height comes in under, force scroll
textTV.contentSize = CGSizeMake(w, initialTVHeight+1); //adding one forces scroll
}
}
F。)添加这些方法,确保键盘仅被用户拖动(不是用户输入新行)解除
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
if ([scrollView isEqual:textTV]){
enableDragDismiss = true;
}
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
if ([scrollView isEqual:textTV]){
enableDragDismiss = false;
}
}
G。)最后,添加此方法,如果用户拖动键盘高度以下,则会解除键盘。
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (enableDragDismiss && [scrollView isEqual:textTV]){
float y = [textTV.panGestureRecognizer locationInView:self.view].y;
float keyboardY = h-keyBoardHeight;
if (y > keyboardY){
enableDragDismiss = false; //allow only once
[textTV resignFirstResponder];
[UIView animateWithDuration:0.5f
delay:0.0f
usingSpringWithDamping:1.0f
initialSpringVelocity:0.8f
options:UIViewAnimationOptionCurveEaseOut
animations:^{
mainScroller.contentOffset = CGPointMake(0, 0);
textTV.contentOffset = CGPointMake(0, 0);
}
completion:^(BOOL finished){
}];
float yOff = 60;
yOff += durationCell.frame.size.height;
yOff += reminderCell.frame.size.height;
yOff += fixedCell.frame.size.height;
yOff += repeatCell.frame.size.height;
textTV.frame = CGRectMake(0, textTV.frame.origin.y, w, h-yOff);
}
}
}
答案 1 :(得分:0)
好的,如果您尝试将UITextView滚动到键盘的“上方”,那么您可以使用-[UITextView textViewDidBeginEditing:]
在初始触摸时修改scrollView的内容偏移量,但是如果您想要每次滚动用户添加换行符或类似内容,您应该可以使用-[UITextView shouldChangeTextInRange:]
,如下所示。
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if ([text isEqualToString:@"\n"]) {
// User has pressed 'return' and entered a new line
// change the content offset + height of line text
self.textView.contentOffset = CGPointMake(x, y);
return NO;
}
return YES;
}
UITextView
继承自UIScrollView
,因此您可以像UIScrollView
中一样更改内容偏移。
答案 2 :(得分:0)
试试这个,它对我有用
- (void)viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField=textField;
}
-(void)keyboardWasShown:(NSNotification *)notification{
float viewWidth = 1024;
float viewHeight = 654;
NSDictionary *keyboardInfo = [notification userInfo];
CGSize keyboardSize = [[keyboardInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
float keyboardHeight = keyboardSize.width;
CGRect viewableAreaFrame = CGRectMake(0.0, 0.0, viewWidth, viewHeight - keyboardHeight);
CGRect txtDemoFrame = [activeField.superview convertRect:activeField.frame toView:self.view];
if (!CGRectContainsRect(viewableAreaFrame, txtDemoFrame)) {
// We need to calculate the new Y offset point.
//float scrollPointY = viewHeight - keyboardHeight;
// Don't forget that the scroller should go to its original position
// so store the current Y point of the content offset.
self.originalScrollerOffsetY = self.SCRVMain.contentOffset.y;
// Finally, scroll.
[self.SCRVMain setContentOffset:CGPointMake(0.0, [activeField.superview convertPoint:activeField.frame.origin toView:self.view].y-200) animated:YES];
}
}
-(void)keyboardWillHide:(NSNotification *)notification{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.SCRVMain.contentInset = contentInsets;
self.SCRVMain.scrollIndicatorInsets = contentInsets;
[self.SCRVMain setContentOffset:CGPointMake(0.0, self.originalScrollerOffsetY) animated:YES];
}
答案 3 :(得分:0)
在我的textViewDidChange中:我已经实现了这样的解决方案(对于非常原始的代码道歉;)):
NSString* substringToSelection = [textView.text substringToIndex:textView.selectedRange.location];
UIFont* textFont = textView.font;
CGRect boundingRect = [substringToSelection boundingRectWithSize:CGSizeMake(textView.frame.size.width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : textFont} context:nil];
CGRect translatedRect = [textView convertRect:boundingRect toView:self.scrollView];
if (!CGRectContainsPoint(self.scrollView.bounds, CGPointMake(CGRectGetMaxX(translatedRect), CGRectGetMaxY(translatedRect))))
{
[self.scrollView scrollRectToVisible:translatedRect animated:YES];
}