问题描述
在iPhone的上下文中:
In the context of the iPhone:
我有一个包含UIImage的UIScrollView。当用户轻击UIImage中的屏幕时,会添加UITextField,用户触摸它。
I have a UIScrollView containing a UIImage. When the user taps the screen inside the UIImage, a UITextField is added where the user touched. The user can edit this UITextField, and the text field will automatically resize itself based on whether text was added or deleted.
当编辑的UITextField增加其宽度时,用户可以编辑此UITextField,并且文本字段将根据是否添加或删除文本自动调整其大小。 scrollview自动滚动以显示增加的宽度。
When the a UITextField being edited increases its width, the scrollview automatically scrolls to show the increased width.
问题出现,因为文本字段的自动滚动不符合屏幕的y值
例如,假设用户在图片底部添加了一个文本字段。当他们去编辑该文本字段时,键盘将显示,隐藏文本字段。我有代码到位滚动屏幕以显示文本字段。当用户输入如此多的文本,以致该文本字段延伸超过屏幕边缘时,问题出现。当这种情况发生时,屏幕水平滚动以适应更宽的文本,但也垂直滚动 - 垂直滚动最终隐藏文本字段,基本上取消任何我显示文本字段。
For example, say the user added a text field to the bottom of the image. When they go to edit that text field, the keyboard will show, hiding the text field. I have code in place to scroll the screen to show the text field. The problem comes in when the user enters so much text that that text field extends past the edge of the screen. When this happens, the screen scrolls horizontally to fit the wider text, but also vertically - the vertical scrolling ends up hiding the textfield, basically nullifying anything I did to show the text field.
如果键盘隐藏,显示文本字段的代码:
Code to show the text field if it's hidden by the keyboard:
- (void)keyboardWasShown:(NSNotification*)notification
{
NSDictionary* info = [notification userInfo];
CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
self.offset = self.contentOffset;
CGRect frame = self.frame;
// self.activeField is the name of the field that is the current first responder - this just adds a little bit of padding
frame.size.height -= keyboardSize.height + (self.activeField.frame.size.height * 2);
if (!CGRectContainsPoint(frame, self.activeField.frame.origin)) {
CGPoint scrollPoint = CGPointMake(self.offset.x, self.activeField.frame.origin.y - keyboardSize.height + (activeField.frame.size.height * 2));
[self setContentOffset:scrollPoint animated:YES];
}
}
这里是增加文本大小的代码字段:
Here is the code to increase the size of the text field:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
CGSize stringSize = [string sizeWithFont:textField.font];
CGSize newSize = [newString sizeWithFont:textField.font];
// Make textField wider if we're close to running up against it
if (newSize.width > (textField.frame.size.width - self.widthOffset)) {
CGRect textFieldFrame = textField.frame;
if (stringSize.width > self.widthOffset) {
textFieldFrame.size.width += stringSize.width;
}
textFieldFrame.size.width += self.widthOffset;
textField.frame = textFieldFrame;
}
// Shrink the textField if there is too much wasted space
if ((textField.frame.size.width - newSize.width) > self.widthOffset) {
CGRect textFieldFrame = textField.frame;
textFieldFrame.size.width = newSize.width + self.widthOffset;
textField.frame = textFieldFrame;
}
return YES;
}
问题是:如何获得UIScrollView尊重
The question is: How do I get the UIScrollView to respect the y-value of itself when automatically scrolling?
推荐答案
基本上UIScrollView的setFrame会重新调整scrollView的偏移量, _adjustContentOffsetIfNecessary。由于该方法是私有的并且没有记录,所以很少有人可以猜测调整将如何发生。
有两种方法来停止不必要的滚动或错误的偏移设置:
Basically setFrame of UIScrollView will readjust the scrollview offset, done by _adjustContentOffsetIfNecessary. As that method is private and not documented, there is very little we can guess on how the adjustment will happen.There are two ways to stop the unnecessary scrolling or wrong offset being set:
1)在应用setFrame之后重置UIScrollView偏移。
1) reset the UIScrollView offset after applying setFrame. This you can do, if you are modifying the frame of UIScrollView intentionally based on some calculations.
CGPoint oldOffset = [scrollView contentOffset];
scrollView.frame = CGRectMake(newFrame);
[scrollView setContentOffset:oldOffset];
2)应用无动画偏移更改。在keyboardWasShown中,更改
[self setContentOffset:scrollPoint animated:YES]; to
[self setContentOffset:scrollPoint animated:NO];
2) apply offset changes without animation. In your keyboardWasShown , change[self setContentOffset:scrollPoint animated:YES]; to
[self setContentOffset:scrollPoint animated:NO];
原因:使用动画时会应用多个偏移,结果偏移不明确。这里的内部方法(_adjustContentOffsetIfNecessary)应用偏移量更改,另一个由您的代码完成。你可以注意到这一点,如果你尝试记录应用于UIScrollView委托方法中的所有偏移:
Reason: when more than one offset is applied with animation on, the result offset is ambiguous. Here the internal method(_adjustContentOffsetIfNecessary) applies an offset change and the other one is done by your code. You can notice this if you try to log all the offsets being applied in the UIScrollView delegate method:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(@" offset: %@", NSStringFromCGPoint(scrollView.conentOffset))
}
让我知道这是否有帮助。
Let me know if this helps.
这篇关于UIKit:当子视图增加其宽度超过屏幕边缘时,UIScrollView自动滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!