Xcode/iOS5:当键盘出现时向上移动 UIView

发布于 2024-12-13 01:22:33 字数 64 浏览 1 评论 0原文

当显示键盘时,我想向上移动我的视图。键盘(高度:216)应该用它的高度来推高我的视野。这可以通过简单的代码实现吗?

I'd like to move up my view, when the keyboard is shown. The keyboard (height: 216) should push up my view with it's height. Is this possible with a simple code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

多孤肩上扛 2024-12-20 01:22:33

向上移动视图,只需更改其中心即可。首先,将原始点保留在 CGPoint 属性中。

- (void)viewDidLoad 
{
    ...
    self.originalCenter = self.view.center;
    ...
}

然后,当键盘出现时根据需要进行更改:

self.view.center = CGPointMake(self.originalCenter.x, /* new calculated y */);

最后,当键盘隐藏时恢复它:

self.view.center = self.originalCenter;

根据需要添加动画糖

您有不止一种方法可以知道键盘何时出现。

观察 UIKeyboardDidShowNotification 通知。

/* register notification in any of your initWithNibName:bundle:, viewDidLoad, awakeFromNib, etc. */
{
    ...
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];     
    ...
}

- (void)keyboardDidShow:(NSNotification *)note 
{
    /* move your views here */
}

使用 UIKeyboardDidHideNotification 执行相反的操作。

-或-

实现 UITextFieldDelegate

检测何时编辑开始/结束以移动视图。

- (void)textFieldDidBeginEditing:(UITextField *)textField 
{
    /* keyboard is visible, move views */
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    /* resign first responder, hide keyboard, move views */
}

根据实际的文本字段,您可能需要跟踪用户在哪个字段中编辑,添加一个计时器以避免过多移动视图。

To move the view up, just change its center. First, keep the original one in a CGPoint property.

- (void)viewDidLoad 
{
    ...
    self.originalCenter = self.view.center;
    ...
}

Then, change as needed when keyboard shows up:

self.view.center = CGPointMake(self.originalCenter.x, /* new calculated y */);

Finally, restore it when keyboard is hidden:

self.view.center = self.originalCenter;

Add animation sugar as you wish

You have more than one way to know when the keyboard appears.

Observing UIKeyboardDidShowNotification notification.

/* register notification in any of your initWithNibName:bundle:, viewDidLoad, awakeFromNib, etc. */
{
    ...
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];     
    ...
}

- (void)keyboardDidShow:(NSNotification *)note 
{
    /* move your views here */
}

Do the opposite with UIKeyboardDidHideNotification.

-OR-

Implement UITextFieldDelegate

Detect when editing begin/end to move views around.

- (void)textFieldDidBeginEditing:(UITextField *)textField 
{
    /* keyboard is visible, move views */
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    /* resign first responder, hide keyboard, move views */
}

Depending on the actual text fields you may need to track in which field is the user editing, add a timer to avoid moving views too much.

笛声青案梦长安 2024-12-20 01:22:33

这样做。
键盘可见后使用此代码

- (void)textFieldDidBeginEditing:(UITextField *)textField 
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.25];
    self.view.frame = CGRectMake(0,-10,320,480);
    [UIView commitAnimations];

}

do like this.
after keyboard visible use this code

- (void)textFieldDidBeginEditing:(UITextField *)textField 
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.25];
    self.view.frame = CGRectMake(0,-10,320,480);
    [UIView commitAnimations];

}
弱骨蛰伏 2024-12-20 01:22:33

我以与 djromero 类似的方式执行此操作,只不过我调整了视图的框架原点而不是其中心。

我正在移动的视图是 UIScrollView,我希望它相对于 UITextField 元素移动,以便文本字段始终显示。该文本字段的位置可能会根据滚动视图的偏移量而变化。

所以我的代码如下所示:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    dispatch_async(dispatch_get_main_queue(), ^{
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.2];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        self.scrollView.frame = CGRectMake(0,0,self.scrollView.frame.size.width,self.scrollView.frame.size.height);
        [UIView commitAnimations];
    });
    return YES;
}

- (NSInteger)getKeyBoardHeight:(NSNotification *)notification
{
    NSDictionary* keyboardInfo = [notification userInfo];
    NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
    CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
    NSInteger keyboardHeight = keyboardFrameBeginRect.size.height;
    return keyboardHeight;
}

-(void) keyboardDidShow:(NSNotification*) notification
{
    NSInteger keyboardHeight;
    keyboardHeight = [self getKeyBoardHeight:notification];
    NSInteger scrollViewFrameHeight = self.scrollView.frame.size.height;
    NSInteger textFieldRelativePosition = self.tableView.frame.origin.y - self.scrollView.contentOffset.y;
    NSInteger textFieldFrameOffset = scrollViewFrameHeight - textFieldRelativePosition;
    NSInteger movement = MAX(0,keyboardHeight-textFieldFrameOffset); // Offset from where the keyboard will appear.
    dispatch_async(dispatch_get_main_queue(), ^{
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.2];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        self.scrollView.frame = CGRectMake(0,-movement,
                                           self.scrollView.frame.size.width,
                                           self.scrollView.frame.size.height);
        [UIView commitAnimations];
    });
}

视图控制器是一个 UITextFieldDelegate,并且还订阅 UIKeyboardDidShowNotification,以便我们能够访问键盘的大小。

当键盘显示时,我们计算 UITextField 的相对偏移量(根据滚动偏移进行调整)和键盘,然后它们更改 UIScrollView 的原点,以便它移动得足以让 UITextField 仍然显示。

如果即使出现键盘,UITextField 仍会显示,则原点不会改变。

I did this in a similar fashion to djromero except that I adjusted the frame origin of the view rather than its centre.

The view that i'm moving is a UIScrollView, and I want it to move relative to a UITextField element, so that the text field always shows. The position of this text field can vary depending on the offset of the scroll view.

So my code looks like this:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    dispatch_async(dispatch_get_main_queue(), ^{
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.2];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        self.scrollView.frame = CGRectMake(0,0,self.scrollView.frame.size.width,self.scrollView.frame.size.height);
        [UIView commitAnimations];
    });
    return YES;
}

- (NSInteger)getKeyBoardHeight:(NSNotification *)notification
{
    NSDictionary* keyboardInfo = [notification userInfo];
    NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
    CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
    NSInteger keyboardHeight = keyboardFrameBeginRect.size.height;
    return keyboardHeight;
}

-(void) keyboardDidShow:(NSNotification*) notification
{
    NSInteger keyboardHeight;
    keyboardHeight = [self getKeyBoardHeight:notification];
    NSInteger scrollViewFrameHeight = self.scrollView.frame.size.height;
    NSInteger textFieldRelativePosition = self.tableView.frame.origin.y - self.scrollView.contentOffset.y;
    NSInteger textFieldFrameOffset = scrollViewFrameHeight - textFieldRelativePosition;
    NSInteger movement = MAX(0,keyboardHeight-textFieldFrameOffset); // Offset from where the keyboard will appear.
    dispatch_async(dispatch_get_main_queue(), ^{
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.2];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        self.scrollView.frame = CGRectMake(0,-movement,
                                           self.scrollView.frame.size.width,
                                           self.scrollView.frame.size.height);
        [UIView commitAnimations];
    });
}

The view controller is a UITextFieldDelegate and also subscribes to UIKeyboardDidShowNotification so that we are able to access the size of the keyboard.

When the keyboard shows, we calculate the relative offset of the UITextField (adjusted for scroll offset) and the keyboard and them change the origin of the UIScrollView so that it moves just enough for the UITextField still to be showing.

If the UITextField will still show even if the keyboard appears, then the origin does not change.

多情癖 2024-12-20 01:22:33

这是实现此目的最简单、最有效的方法:

添加以下常量:

static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;    

将其添加到您的视图控制器:

CGFloat animatedDistance;

并将这些方法添加到您的代码中:

- (void)textFieldDidBeginEditing:(UITextField *)textField{
CGRect textFieldRect =
[self.view.window convertRect:textField.bounds fromView:textField];
CGRect viewRect =
[self.view.window convertRect:self.view.bounds fromView:self.view];
CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;
CGFloat numerator =
midline - viewRect.origin.y
- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
CGFloat denominator =
(MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)
* viewRect.size.height;
CGFloat heightFraction = numerator / denominator;
if (heightFraction < 0.0)
{
    heightFraction = 0.0;
}
else if (heightFraction > 1.0)
{
    heightFraction = 1.0;
}
UIInterfaceOrientation orientation =
[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait ||
    orientation == UIInterfaceOrientationPortraitUpsideDown)
{
    animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
}
else
{
    animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
}
CGRect viewFrame = self.view.frame;
viewFrame.origin.y -= animatedDistance;

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

[self.view setFrame:viewFrame];

[UIView commitAnimations];
}

- (void)textFieldDidEndEditing:(UITextField *)textfield{

CGRect viewFrame = self.view.frame;
viewFrame.origin.y += animatedDistance;

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

[self.view setFrame:viewFrame];

[UIView commitAnimations];
}

This is the most easiest and efficient way to achieve this:

Add the following constants:

static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;    

Add this to your view controller:

CGFloat animatedDistance;

And add these methods to your code:

- (void)textFieldDidBeginEditing:(UITextField *)textField{
CGRect textFieldRect =
[self.view.window convertRect:textField.bounds fromView:textField];
CGRect viewRect =
[self.view.window convertRect:self.view.bounds fromView:self.view];
CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;
CGFloat numerator =
midline - viewRect.origin.y
- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
CGFloat denominator =
(MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)
* viewRect.size.height;
CGFloat heightFraction = numerator / denominator;
if (heightFraction < 0.0)
{
    heightFraction = 0.0;
}
else if (heightFraction > 1.0)
{
    heightFraction = 1.0;
}
UIInterfaceOrientation orientation =
[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait ||
    orientation == UIInterfaceOrientationPortraitUpsideDown)
{
    animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
}
else
{
    animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
}
CGRect viewFrame = self.view.frame;
viewFrame.origin.y -= animatedDistance;

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

[self.view setFrame:viewFrame];

[UIView commitAnimations];
}

- (void)textFieldDidEndEditing:(UITextField *)textfield{

CGRect viewFrame = self.view.frame;
viewFrame.origin.y += animatedDistance;

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

[self.view setFrame:viewFrame];

[UIView commitAnimations];
}
開玄 2024-12-20 01:22:33

假设您有一些代码调用 [myTextFieldBecomeFirstResponder];。您应该在这次通话之后立即移动您的视图。

Presumably you have some code calling [myTextField becomeFirstResponder];. You should move your view just after this call.

清醇 2024-12-20 01:22:33
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    CGFloat y = textField.frame.origin.y;
    if (y >= 350) //not 380
   {
        CGRect frame = self.view.frame;
        frame.origin.y = 320 - textField.frame.origin.y;
        [UIView animateWithDuration:0.3 animations:^{self.view.frame = frame;}];
    }
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
CGRect returnframe =self.view.frame;
returnframe.origin.y = 0;
[UIView animateWithDuration:0.3 animations:^{self.view.frame = frame;}];
}

只需编辑这两个方法即可。
所有 d 代码的简单答案。在if语句中根据iphone更改值,如果iphone 4S将其更改为265,在didbeginediting中将320更改为240,如果iphone 5将其更改为350,在didbeginediting方法中将其保留为320,因为这是逻辑如果你明白的话

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    CGFloat y = textField.frame.origin.y;
    if (y >= 350) //not 380
   {
        CGRect frame = self.view.frame;
        frame.origin.y = 320 - textField.frame.origin.y;
        [UIView animateWithDuration:0.3 animations:^{self.view.frame = frame;}];
    }
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
CGRect returnframe =self.view.frame;
returnframe.origin.y = 0;
[UIView animateWithDuration:0.3 animations:^{self.view.frame = frame;}];
}

just edit these two methods.
simple answer to all d codes. In the if statement change the value according to the iphone i.e., if iphone 4S change it to 265 and in didbeginediting change the 320 to 240 and if iphone 5 change it to 350 and in didbeginediting method keep it as 320, because it is the logic if u understand

躲猫猫 2024-12-20 01:22:33

这是 Tendulkar 解决方案,但请记住原始框架尺寸并移除键盘。该解决方案适用于所有设备。

-(BOOL) textFieldShouldReturn:(UITextField *)textField{

[textField resignFirstResponder];

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
self.view.frame = CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height);
[UIView commitAnimations];
return YES;
 }


- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.25];
    self.view.frame = CGRectMake(0,-50,self.view.frame.size.width,self.view.frame.size.height);
    [UIView commitAnimations];

}

不要忘记设置 UITextField 委托!

This is Tendulkar solution, but keeping in mind original frame size and removing keyboard. This solution works for all devices.

-(BOOL) textFieldShouldReturn:(UITextField *)textField{

[textField resignFirstResponder];

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
self.view.frame = CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height);
[UIView commitAnimations];
return YES;
 }


- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.25];
    self.view.frame = CGRectMake(0,-50,self.view.frame.size.width,self.view.frame.size.height);
    [UIView commitAnimations];

}

Do not forget set UITextField delegate!

金橙橙 2024-12-20 01:22:33

示例项目基于 苹果参考 键盘文档

H 文件:(不要忘记UITextFieldDelegate)

@property (weak, nonatomic) IBOutlet UIScrollView *scrollview;

@property (weak, nonatomic) IBOutlet UIView *myView;


    //items on view
@property (weak, nonatomic) IBOutlet UISwitch *partySwitch;
@property (weak, nonatomic) IBOutlet UILabel *partyLabel;
@property (weak, nonatomic) IBOutlet UITextField *partyNameTextfield;

M 文件:

    //MARK: View Loading
- (void)viewDidLoad
{
    [super viewDidLoad];
        // Do any additional setup after loading the view.
}//eom

-(void)viewDidAppear:(BOOL)animated
{
    [self registerForKeyboardNotifications];
}//eom

    //MARK: textfield delegates
-(bool)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return true;
}//eom

    //MARK: - Keyboard Observers
    // Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification object:nil];

}


- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info      = [aNotification userInfo];
    CGSize kbSize           = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect bkgndRect        = myView.superview.frame;
    bkgndRect.size.height += kbSize.height;

    [myView.superview setFrame:bkgndRect];
    [scrollview setContentOffset:CGPointMake(0.0, myView.frame.origin.y-kbSize.height) animated:YES];
}//eom

    // Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets          = UIEdgeInsetsZero;
    scrollview.contentInset             = contentInsets;
    scrollview.scrollIndicatorInsets    = contentInsets;
}//eom

Sample project Based on Apple Reference Keyboard Documentation

H File: (Don't Forget the UITextFieldDelegate)

@property (weak, nonatomic) IBOutlet UIScrollView *scrollview;

@property (weak, nonatomic) IBOutlet UIView *myView;


    //items on view
@property (weak, nonatomic) IBOutlet UISwitch *partySwitch;
@property (weak, nonatomic) IBOutlet UILabel *partyLabel;
@property (weak, nonatomic) IBOutlet UITextField *partyNameTextfield;

M file:

    //MARK: View Loading
- (void)viewDidLoad
{
    [super viewDidLoad];
        // Do any additional setup after loading the view.
}//eom

-(void)viewDidAppear:(BOOL)animated
{
    [self registerForKeyboardNotifications];
}//eom

    //MARK: textfield delegates
-(bool)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return true;
}//eom

    //MARK: - Keyboard Observers
    // Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification object:nil];

}


- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info      = [aNotification userInfo];
    CGSize kbSize           = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect bkgndRect        = myView.superview.frame;
    bkgndRect.size.height += kbSize.height;

    [myView.superview setFrame:bkgndRect];
    [scrollview setContentOffset:CGPointMake(0.0, myView.frame.origin.y-kbSize.height) animated:YES];
}//eom

    // Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets          = UIEdgeInsetsZero;
    scrollview.contentInset             = contentInsets;
    scrollview.scrollIndicatorInsets    = contentInsets;
}//eom
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文