Xcode 中键盘弹出时向上移动框架

发布于 2024-12-11 17:11:40 字数 5508 浏览 0 评论 0原文

#import "LoginScreen.h"

#define kTabBarHeight 1
#define kKeyboardAnimationDuration 0.3


@implementation LoginScreen

@synthesize userName,password,loginButton,scrollView;

BOOL keyboardIsShown;


 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization.

    }
    return self;
}


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillShow:) 
                                                 name:UIKeyboardWillShowNotification 
                                               object:self.view.window];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillHide:) 
                                                 name:UIKeyboardWillHideNotification 
                                               object:self.view.window];
    keyboardIsShown = NO;
    //make contentSize bigger than your scrollSize (you will need to figure out for your own use case)
    // CGSize scrollContentSize = CGSizeMake(1024,700 );
    // [scrollView setContentSize : scrollContentSize];
    self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
}



- (void)keyboardWillHide:(NSNotification *)n
{
    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    NSValue* boundsValue = [userInfo objectForKey:UIKeyboardBoundsUserInfoKey];
    CGSize keyboardSize = [boundsValue CGRectValue].size;


    // resize the scrollview
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height += (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    // The kKeyboardAnimationDuration I am using is 0.3
    [UIView setAnimationDuration:kKeyboardAnimationDuration];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];

    keyboardIsShown = NO;
}

- (void)keyboardWillShow:(NSNotification *)n
{
    // This is an ivar I'm using to ensure that we do not do the frame size adjustment on the UIScrollView if the keyboard is already shown.  This can happen if the user, after fixing editing a UITextField, scrolls the resized UIScrollView to another UITextField and attempts to edit the next UITextField.  If we were to resize the UIScrollView again, it would be disastrous.  NOTE: The keyboard notification will fire even when the keyboard is already shown.
    if (keyboardIsShown) {
        return;
    }

    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    NSValue* boundsValue = [userInfo objectForKey:UIKeyboardBoundsUserInfoKey];
    CGSize keyboardSize = [boundsValue CGRectValue].size;

    // resize the noteView
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height -= (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    // The kKeyboardAnimationDuration I am using is 0.3
    [UIView setAnimationDuration:kKeyboardAnimationDuration];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];

    keyboardIsShown = YES;
}



- (IBAction) loginButton: (id) sender{


}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Overriden to allow any orientation.
    return YES;
}


- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc. that aren't in use.
}


- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;

    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self 
                                                    name:UIKeyboardWillShowNotification 
                                                  object:nil]; 
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self 
                                                    name:UIKeyboardWillHideNotification 
                                                  object:nil];  

}



- (void)dealloc {
    [scrollView release];
    [super dealloc];
}


@end

谁能告诉我下面的代码有什么问题。即使我将键盘高度减去框架高度,原始视图也不会向上移动。

当键盘弹出时,scrollView不会向上移动?我在这里缺少一些代码吗?

#import "LoginScreen.h"

#define kTabBarHeight 1
#define kKeyboardAnimationDuration 0.3


@implementation LoginScreen

@synthesize userName,password,loginButton,scrollView;

BOOL keyboardIsShown;


 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization.

    }
    return self;
}


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillShow:) 
                                                 name:UIKeyboardWillShowNotification 
                                               object:self.view.window];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillHide:) 
                                                 name:UIKeyboardWillHideNotification 
                                               object:self.view.window];
    keyboardIsShown = NO;
    //make contentSize bigger than your scrollSize (you will need to figure out for your own use case)
    // CGSize scrollContentSize = CGSizeMake(1024,700 );
    // [scrollView setContentSize : scrollContentSize];
    self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
}



- (void)keyboardWillHide:(NSNotification *)n
{
    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    NSValue* boundsValue = [userInfo objectForKey:UIKeyboardBoundsUserInfoKey];
    CGSize keyboardSize = [boundsValue CGRectValue].size;


    // resize the scrollview
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height += (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    // The kKeyboardAnimationDuration I am using is 0.3
    [UIView setAnimationDuration:kKeyboardAnimationDuration];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];

    keyboardIsShown = NO;
}

- (void)keyboardWillShow:(NSNotification *)n
{
    // This is an ivar I'm using to ensure that we do not do the frame size adjustment on the UIScrollView if the keyboard is already shown.  This can happen if the user, after fixing editing a UITextField, scrolls the resized UIScrollView to another UITextField and attempts to edit the next UITextField.  If we were to resize the UIScrollView again, it would be disastrous.  NOTE: The keyboard notification will fire even when the keyboard is already shown.
    if (keyboardIsShown) {
        return;
    }

    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    NSValue* boundsValue = [userInfo objectForKey:UIKeyboardBoundsUserInfoKey];
    CGSize keyboardSize = [boundsValue CGRectValue].size;

    // resize the noteView
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height -= (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    // The kKeyboardAnimationDuration I am using is 0.3
    [UIView setAnimationDuration:kKeyboardAnimationDuration];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];

    keyboardIsShown = YES;
}



- (IBAction) loginButton: (id) sender{


}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Overriden to allow any orientation.
    return YES;
}


- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc. that aren't in use.
}


- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;

    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self 
                                                    name:UIKeyboardWillShowNotification 
                                                  object:nil]; 
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self 
                                                    name:UIKeyboardWillHideNotification 
                                                  object:nil];  

}



- (void)dealloc {
    [scrollView release];
    [super dealloc];
}


@end

Can anybody tell me whats wrong in code below. The original view doesn't move up even though i am subtracting the keyboards height to the frame heights.

The scrollView doesn't move up when keyboard pops in? Am I missing some code here.

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

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

发布评论

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

评论(1

删除会话 2024-12-18 17:11:40

好吧,问题是您没有告诉代码文本字段从哪里开始,因此它不知道需要从哪里滚动。您可能认为您的 self.scrollView.frame 可以做到这一点,但这只是告诉代码您的 ScrollView 的大小,而不是它需要滚动或应该滚动。这就是我为让我的工作正常工作所做的事情。

查看其中一个文本字段的连接。将“Did Begin Editing”和“Did End Editing”拖放到 .h 文件中以创建 IBAction 函数声明。 Xcode 会将函数放入 .m 中,但将它们替换为以下内容:

//even though these functions don't reference the IBAction that we placed for the 
"DidBeginEditing" sender for a text field, it will still call these functions.
We need to let the code know what text field we just touched so we can go through
the functions that reset the view size if the text field is under the keyboard.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    currentTextField = textField;
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    currentTextField = nil;
}

这提醒了我,您需要在 .m 中将 currentTextField 声明为 UITextField *:

@interface ThirdView : UIViewController{
    UITextField *currentTextField;
    BOOL keyboardIsShown;
}

我的 viewDidLoad、keyBoardWasShown 等与您的有点不同,但我会把它们全部放在这里,这样你就可以看到我是如何让它工作的:

//This is code you actually add to get the view to scroll.
You should first connect an outlet from the ScrollView to the .h file so these
functions become available.

- (void)viewDidLoad {


    //standard screen size is 320 X 460

   // ---set the viewable frame of the scroll view---

    //  scrollView.frame = CGRectMake(0, 0, 320, 460);


    //---set the content size of the scroll view---

    //  [scrollView setContentSize:CGSizeMake(320, 615)];  


    //the status bar is 20 pixels tall 

    //the navigation bar is 44 pixels tall


    //---set the viewable frame of the scroll view---

    //Note: for some reason, the origin (0,44) doesn't take into account the status bar, but it works anyway.  However, the height of the scroll view does take it into account.  Wierd, but whatever.  So you have to make y1 = 44, and y2 = 460-44-20.

      scrollView.frame = CGRectMake(0, 44, 320, 416);

    //---set the content size of the scroll view---

      [scrollView setContentSize:CGSizeMake(320, 571)]; 

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];

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

    [super viewDidLoad];
}



- (void)viewDidUnload
{

    [self setPrincipal_Amt:nil];

    [self setAPR:nil];

    [self setYears:nil];

    [self setScrollView:nil];

    [super viewDidUnload];

    // Release any retained subviews of the main view.

    // e.g. self.myOutlet = nil;

}

// Called when the UIKeyboardDidShowNotification is sent.

- (void)keyboardWasShown:(NSNotification*)aNotification
{

    if(keyboardIsShown)
        return;

    NSDictionary* info = [aNotification userInfo];

    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);

    scrollView.contentInset = contentInsets;

    scrollView.scrollIndicatorInsets = contentInsets;

    // If active text field is hidden by keyboard, scroll it so it's visible
     Notice that we've got to add 64 pixels to the keyboard height because the CGRect has
     no idea that you have the status bar shown and a navigation bar within your view, so
     you have to manually add it in.

    CGRect aRect = self.view.frame;

    aRect.size.height -= (kbSize.height + 64);

    if (!CGRectContainsPoint(aRect, currentTextField.frame.origin) ) 
    {
        CGPoint scrollPoint = CGPointMake(0.0, currentTextField.frame.origin.y-kbSize.height + 64);

        [scrollView setContentOffset:scrollPoint animated:YES];

    }

    keyboardIsShown = YES;

}

// Called when the UIKeyboardWillHideNotification is sent

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{

    UIEdgeInsets contentInsets = UIEdgeInsetsZero;

    scrollView.contentInset = contentInsets;

    scrollView.scrollIndicatorInsets = contentInsets;


    keyboardIsShown = NO;

}
//

我希望这会有所帮助......即使你不久前确实发布了这个:)我也花了一段时间才让它工作。非常令人沮丧。

Well, the problem is that you're not telling your code where your text field is to begin with, so it has no idea where it needs to scroll from. You probably thought that your self.scrollView.frame does it, but that only tells the code the size of your ScrollView, not that it needs to scroll or should scroll. Here's what I did to get mine to work.

Look at the connections for one of your text fields. Drag and drop from the "Did Begin Editing" and "Did End Editing" into your .h file to create IBAction function declarations. Xcode is going to put functions into the .m, but replace them with these:

//even though these functions don't reference the IBAction that we placed for the 
"DidBeginEditing" sender for a text field, it will still call these functions.
We need to let the code know what text field we just touched so we can go through
the functions that reset the view size if the text field is under the keyboard.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    currentTextField = textField;
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    currentTextField = nil;
}

That reminds me, you'll need to declare currentTextField as a UITextField * in the .m:

@interface ThirdView : UIViewController{
    UITextField *currentTextField;
    BOOL keyboardIsShown;
}

My viewDidLoad, keyBoardWasShown, etc are a bit different from yours, but I'll just put them all here so you can see how I got it to work:

//This is code you actually add to get the view to scroll.
You should first connect an outlet from the ScrollView to the .h file so these
functions become available.

- (void)viewDidLoad {


    //standard screen size is 320 X 460

   // ---set the viewable frame of the scroll view---

    //  scrollView.frame = CGRectMake(0, 0, 320, 460);


    //---set the content size of the scroll view---

    //  [scrollView setContentSize:CGSizeMake(320, 615)];  


    //the status bar is 20 pixels tall 

    //the navigation bar is 44 pixels tall


    //---set the viewable frame of the scroll view---

    //Note: for some reason, the origin (0,44) doesn't take into account the status bar, but it works anyway.  However, the height of the scroll view does take it into account.  Wierd, but whatever.  So you have to make y1 = 44, and y2 = 460-44-20.

      scrollView.frame = CGRectMake(0, 44, 320, 416);

    //---set the content size of the scroll view---

      [scrollView setContentSize:CGSizeMake(320, 571)]; 

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];

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

    [super viewDidLoad];
}



- (void)viewDidUnload
{

    [self setPrincipal_Amt:nil];

    [self setAPR:nil];

    [self setYears:nil];

    [self setScrollView:nil];

    [super viewDidUnload];

    // Release any retained subviews of the main view.

    // e.g. self.myOutlet = nil;

}

// Called when the UIKeyboardDidShowNotification is sent.

- (void)keyboardWasShown:(NSNotification*)aNotification
{

    if(keyboardIsShown)
        return;

    NSDictionary* info = [aNotification userInfo];

    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);

    scrollView.contentInset = contentInsets;

    scrollView.scrollIndicatorInsets = contentInsets;

    // If active text field is hidden by keyboard, scroll it so it's visible
     Notice that we've got to add 64 pixels to the keyboard height because the CGRect has
     no idea that you have the status bar shown and a navigation bar within your view, so
     you have to manually add it in.

    CGRect aRect = self.view.frame;

    aRect.size.height -= (kbSize.height + 64);

    if (!CGRectContainsPoint(aRect, currentTextField.frame.origin) ) 
    {
        CGPoint scrollPoint = CGPointMake(0.0, currentTextField.frame.origin.y-kbSize.height + 64);

        [scrollView setContentOffset:scrollPoint animated:YES];

    }

    keyboardIsShown = YES;

}

// Called when the UIKeyboardWillHideNotification is sent

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{

    UIEdgeInsets contentInsets = UIEdgeInsetsZero;

    scrollView.contentInset = contentInsets;

    scrollView.scrollIndicatorInsets = contentInsets;


    keyboardIsShown = NO;

}
//

I hope that helps...even though you did post this a while ago :) It took me a while to get it to work too. Very frustrating.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文