[英]How to resize UITextView on iOS when a keyboard appears?
在UITabBarController
(在iPhone上)的選項卡中插入了UITextView
。
UITextView
。 發生了什么? 鍵盤用光標隱藏了一半的UITextView
。 無法編輯文本作為結果。
如何解決所有Apple移動設備(具有不同屏幕分辨率)的問題? 非常感謝您的幫助!
以下代碼達到了最佳結果。 另外不要忘了背景色設置為UIView
並將UITextView
前等頂級屏幕控制(如UITabBar)。
最后編輯文本仍然不完美。 你可以嘗試改進。
FirstViewController.h:
@interface FirstViewController : UIViewController {
IBOutlet UIBarButtonItem *buttonDone;
IBOutlet UITextView *textView;
UITabBarController* tabBarController; // set from superview in AppDelegate (MainWindow.xib)
}
@property (nonatomic, retain) UITabBarController* tabBarController;
FirstViewController.m:
@synthesize tabBarController;
- (void)viewDidAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShown:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)moveTextViewForKeyboard:(NSNotification*)aNotification up:(BOOL)up {
NSDictionary* userInfo = [aNotification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
CGRect newFrame = textView.frame;
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
keyboardFrame.size.height -= tabBarController.tabBar.frame.size.height;
newFrame.size.height -= keyboardFrame.size.height * (up?1:-1);
textView.frame = newFrame;
[UIView commitAnimations];
}
- (void)keyboardWillShown:(NSNotification*)aNotification
{
buttonDone.enabled = true;
[self moveTextViewForKeyboard:aNotification up:YES];
}
- (void)keyboardWillHide:(NSNotification*)aNotification
{
buttonDone.enabled = false;
[self moveTextViewForKeyboard:aNotification up:NO];
}
PS沒有stackoverflow就很難為iOS編碼......
我遇到了幾個問題,試圖讓我的文本視圖能夠正確地滾動和動畫,適用於iOS 7和iOS 8,以及新的QuickType功能。 起初我專注於動畫滾動視圖插圖,但iOS 7和8之間的行為不同,並且無法使兩者都正常工作。
然后我意識到我可以通過專注於框架簡化事情,這對我來說有更多簡單的代碼。 綜上所述:
UIKeyboardDidChangeFrameNotification
(這將在QuickType顯示/隱藏時通知)。 以下是一些說明上述內容的代碼:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidChangeFrameWithNotification:) name:UIKeyboardDidChangeFrameNotification object:nil];
}
- (void)keyboardDidChangeFrameWithNotification:(NSNotification *)notification {
CGFloat keyboardVerticalIncrease = [self keyboardVerticalIncreaseForNotification:notification];
[self animateTextViewFrameForVerticalOffset:keyboardVerticalIncrease];
}
- (CGFloat)keyboardVerticalIncreaseForNotification:(NSNotification *)notification {
CGFloat keyboardBeginY = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].origin.y;
CGFloat keyboardEndY = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y;
CGFloat keyboardVerticalIncrease = keyboardBeginY - keyboardEndY;
return keyboardVerticalIncrease;
}
- (void)animateTextViewFrameForVerticalOffset:(CGFloat)offset {
CGFloat constant = self.bottomConstraint.constant;
CGFloat newConstant = constant + offset;
self.bottomConstraint.constant = newConstant;
[self.view layoutIfNeeded];
[UIView animateWithDuration:0.5 animations:^{
[self.view layoutIfNeeded];
}];
}
關於動畫的快速說明。 我使用了Autolayout,因此我選擇為文本視圖的NSAutoLayoutConstraint設置動畫,而不是直接設置框架。 為此,我在動畫塊之前和之內調用[self.view layoutIfNeeded]
。 這是動畫約束的正確方法。 我在這里找到了這個提示。
值得注意的是,只有當設備處於縱向模式(而不是顛倒)時,upvoted答案才有效,在其他模式下,邊界出錯。 我相信你可以通過使用邊界來修復它,但我無法讓它工作,所以下面的調整對我有用:
- (void)moveTextViewForKeyboard:(NSNotification*)aNotification up:(BOOL)up {
NSDictionary* userInfo = [aNotification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
CGRect newFrame = self.view.frame;
if (keyboardEndFrame.size.height >keyboardEndFrame.size.width)
{ //we must be in landscape
if (keyboardEndFrame.origin.x==0)
{ //upside down so need to flip origin
newFrame.origin = CGPointMake(keyboardEndFrame.size.width, 0);
}
newFrame.size.width -= keyboardEndFrame.size.width * (up?1:-1);
} else
{ //in portrait
if (keyboardEndFrame.origin.y==0)
{
//upside down so need to flip origin
newFrame.origin = CGPointMake(0, keyboardEndFrame.size.height);
}
newFrame.size.height -= keyboardEndFrame.size.height * (up?1:-1);
}
self.view.frame = newFrame;
[UIView commitAnimations];
}
- (void)registerKeyboardNotifications
{
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)unregisterKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void) keyboardWillHide:(NSNotification *)note
{
//adjust frame
}
-(void) keyboardWillShow:(NSNotification *)note
{
//adjust frame
}
並且在dealloc中也注銷了Notification
- (void)unregisterKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
多年過去了,這個問題仍然存在。 Apple絕對應該自己處理所有這些事情。 但事實並非如此。 這是基於官方Apple 文檔和錯誤修復的新解決方案。 它支持iOS 8,iOS 9,inputAccessoryView,可以用於新版本的iOS和新設備。
/* Apple's solution to resize keyboard but with accessory view support */
- (void)keyboardDidShow:(NSNotification*)aNotification {
NSDictionary* info = [aNotification userInfo];
CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
double keyboardHeight = [[UIScreen mainScreen] bounds].size.height - keyboardFrame.origin.y;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardHeight, 0.0);
editor.contentInset = contentInsets;
editor.scrollIndicatorInsets = contentInsets;
}
- (void)keyboardWillHide:(NSNotification*)aNotification {
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
editor.contentInset = contentInsets;
editor.scrollIndicatorInsets = contentInsets;
// button to hide the keyboard
buttonDone.enabled = false;
}
/* Fix issues with size classes and accessory view */
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
// fix incorrect size of the inputAccessoryView when size class changed
// willTransitionToTraitCollection and traitCollectionDidChange can't help us
if (editor && editor.inputAccessoryView && !editor.inputAccessoryView.hidden) {
[editor resignFirstResponder];
}
}
/* Hide accessory view if a hardware keyboard is present */
#define gThresholdForHardwareKeyboardToolbar 160.f // it's minimum height of the software keyboard on iPhone 4 in landscape mode
- (bool)isExternalKeyboard:(NSNotification*)aNotification {
NSDictionary* info = [aNotification userInfo];
CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
double keyboardHeight = [[UIScreen mainScreen] bounds].size.height - keyboardFrame.origin.y;
return keyboardHeight < gThresholdForHardwareKeyboardToolbar;
}
- (void)keyboardWillShow:(NSNotification*)aNotification {
if ([self isExternalKeyboard:aNotification]) {
// hardware keyboard is present
if (editor && editor.inputAccessoryView) {
editor.inputAccessoryView.hidden = true;
}
} else {
// only on-screen keyboard
if (editor && editor.inputAccessoryView) {
editor.inputAccessoryView.hidden = false;
}
}
// button to hide the keyboard
buttonDone.enabled = true;
}
首先將一些鍵盤方法添加到NSNotificationCenter
defaultCenter
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:self.view.window];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification object:self.view.window];
然后你可以改變大小:
- (void)keyboardWillShow:(NSNotification *)notif
{
[thetextView setFrame:CGRectMake(20, 49, 280, 187)]; //Or where ever you want the view to go
}
- (void)keyboardWillHide:(NSNotification *)notif
{
[thetextView setFrame:CGRectMake(20, 49, 280, 324)]; //return it to its original position
}
作為后續操作,在鍵盤通知發生時更新幀的技術對iOS 7不起作用。對於替代解決方案,請參閱以下內容:
我在這里嘗試了最好的答案但是我發現了一個問題。 如果您在同一頁面上有另一個文本字段,則單擊文本字段,顯示鍵盤。 您會注意到文本視圖縮小了。 但是,如果現在單擊文本視圖,您會注意到文本視圖大小再次縮小,而不應該。
我對這個問題的解決方案是在視圖控制器中維護一個表示鍵盤狀態的屬性(顯示/隱藏)。 如果鍵盤當前可見,則不應縮小文本視圖。 如果您使用不同大小的鍵盤進行不同的文本輸入,您還應該保持舊的鍵盤大小。
請注意,此解決方案也沒有考慮不同的方向,這可能會影響您計算文本視圖大小的方式。
@implementation MyViewController {
BOOL keyboardShown;
NSInteger keyboardHeight;
}
- (void)moveTextViewForKeyboard:(NSNotification*)aNotification up: (BOOL) up{
NSDictionary* userInfo = [aNotification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
CGRect newFrame = self.textView.frame;
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
NSInteger oldHeight = self->keyboardShown ? self->keyboardHeight : 0;
NSInteger newHeight = up ? keyboardFrame.size.height : 0;
NSInteger change = oldHeight - newHeight;
self->keyboardShown = up;
self->keyboardHeight = keyboardFrame.size.height;
newFrame.size.height += change;
self.textView.frame = newFrame;
[UIView commitAnimations];
}
簡而言之,注冊鍵盤通知並在收到通知后進行重新調整大小的工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.