恕我直言,这是 iOS 7 中所有典型 UITextView 滚动/键盘相关问题的最终答案。它干净、易于阅读、易于使用、易于维护且易于重用。
基本技巧:
只需更改 UITextView 的大小,而不是内容插图!
这是一个动手的例子。您理所当然地拥有一个使用 Autolayout 的基于 NIB/Storyboard 的 UIViewController,并且 UITextView 填充了 UIViewController 中的整个根视图。如果不是,您将不得不根据您的需要调整更改 textViewBottomSpaceConstraint 的方式。
如何:
添加这些属性:
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *textViewBottomSpaceConstraint;
@property (nonatomic) CGFloat textViewBottomSpaceConstraintFromNIB;
在 Interface Builder 中连接 textViewBottomSpaceConstraint(不要忘记!)
然后在 viewDidLoad 中:
// Save the state of the UITextView's bottom constraint as set up in your NIB/Storyboard
self.textViewBottomSpaceConstraintFromNIB = self.textViewBottomSpaceConstraint.constant;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShowNotification:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHideNotification:)
name:UIKeyboardWillHideNotification
object:nil];
添加这些方法来处理键盘大小调整(感谢https://github.com/brennanMKE/Interfaces/tree/master/Keyboarding - 这些方法由 brennan 提供!):
- (void)keyboardWillShowNotification:(NSNotification *)notification {
CGFloat height = [self getKeyboardHeight:notification forBeginning:TRUE];
NSTimeInterval duration = [self getDuration:notification];
UIViewAnimationOptions curve = [self getAnimationCurve:notification];
[self keyboardWillShowWithHeight:height duration:duration curve:curve];
}
- (void)keyboardWillHideNotification:(NSNotification *)notification {
CGFloat height = [self getKeyboardHeight:notification forBeginning:FALSE];
NSTimeInterval duration = [self getDuration:notification];
UIViewAnimationOptions curve = [self getAnimationCurve:notification];
[self keyboardWillHideWithHeight:height duration:duration curve:curve];
}
- (NSTimeInterval)getDuration:(NSNotification *)notification {
NSDictionary *info = [notification userInfo];
NSTimeInterval duration;
NSValue *durationValue = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
[durationValue getValue:&duration];
return duration;
}
- (CGFloat)getKeyboardHeight:(NSNotification *)notification forBeginning:(BOOL)forBeginning {
NSDictionary *info = [notification userInfo];
CGFloat keyboardHeight;
NSValue *boundsValue = nil;
if (forBeginning) {
boundsValue = [info valueForKey:UIKeyboardFrameBeginUserInfoKey];
}
else {
boundsValue = [info valueForKey:UIKeyboardFrameEndUserInfoKey];
}
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (UIDeviceOrientationIsLandscape(orientation)) {
keyboardHeight = [boundsValue CGRectValue].size.width;
}
else {
keyboardHeight = [boundsValue CGRectValue].size.height;
}
return keyboardHeight;
}
- (UIViewAnimationOptions)getAnimationCurve:(NSNotification *)notification {
UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
switch (curve) {
case UIViewAnimationCurveEaseInOut:
return UIViewAnimationOptionCurveEaseInOut;
break;
case UIViewAnimationCurveEaseIn:
return UIViewAnimationOptionCurveEaseIn;
break;
case UIViewAnimationCurveEaseOut:
return UIViewAnimationOptionCurveEaseOut;
break;
case UIViewAnimationCurveLinear:
return UIViewAnimationOptionCurveLinear;
break;
}
return kNilOptions;
}
最后,添加这些方法来响应键盘通知并调整 UITextView 的大小
- (void)keyboardWillShowWithHeight:(CGFloat)height duration:(CGFloat)duration curve:(UIViewAnimationOptions)curve
{
CGFloat correctionMargin = 15; // you can experiment with this margin so the bottom text view line is not flush against the keyboard which doesn't look nice
self.textViewBottomSpaceConstraint.constant = height + correctionMargin;
[self.view setNeedsUpdateConstraints];
[UIView animateWithDuration:duration delay:0 options:curve animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
}];
}
- (void)keyboardWillHideWithHeight:(CGFloat)height duration:(CGFloat)duration curve:(UIViewAnimationOptions)curve
{
self.textViewBottomSpaceConstraint.constant = self.textViewBottomSpaceConstraintFromNIB;
[self.view setNeedsUpdateConstraints];
[UIView animateWithDuration:duration delay:0 options:curve animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
}];
}
还添加这些方法以自动滚动到用户单击的位置
- (void)textViewDidBeginEditing:(UITextView *)textView
{
[textView scrollRangeToVisible:textView.selectedRange];
}
- (void)textViewDidChangeSelection:(UITextView *)textView
{
[textView scrollRangeToVisible:textView.selectedRange];
}