【问题标题】:UIScrollView moves down when I make exit from a popped view controller当我从弹出的视图控制器退出时,UIScrollView 向下移动
【发布时间】:2013-11-14 06:26:34
【问题描述】:

导航控制器和 2 个视图控制器有问题。当我弹出到其他视图控制器时一切正常,但是当我返回我的第一个视图时,它会在导航栏下显示一个 白色的大地方

在第二个控制器上,当我编辑 UITextField 时,我的键盘会自动显示和隐藏。 当我从显示键盘的第二个视图控制器返回时,这个问题就开始了。 其他方式(不编辑 UITextField)我第一个控制器没有这个问题。

我需要做什么?

第一个 .m 文件

#import "OTPTRecordViewController.h"
#import "OTPTAppDelegate.h"
#import "OTPTPractice.h"


@implementation OTPTRecordViewController
@synthesize scrollView, activeField;

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self registerForKeyboardNotifications];

    viewBackgroundTap.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:viewBackgroundTap];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(-20.0, 0.0, 0.0, 0.0);
    //I need it for correct view insets

    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;    
}

#pragma mark Textfields&Keyboard management

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return NO;
}

- (IBAction)backgroundTap:(id)sender
{
    [nameTextField resignFirstResponder];
    [lengthTextField resignFirstResponder];    
}

- (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;

    if (([holdOutTextField isEditing]) || ([cyclesTextField isEditing])) {
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height+50.0, 0.0);
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }       

    CGRect aRect = self.view.frame;
    //For scroll view moves
    aRect.size.height -= kbSize.height + self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height;
    CGPoint origin = activeField.frame.origin;
    origin.y -= scrollView.contentOffset.y;
    if (!CGRectContainsPoint(aRect, origin) ) {
        CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-(aRect.size.height));
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(-20.0, 0.0, 0.0, 0.0);

    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    activeField = textField;
    [activeField setSelectedTextRange:[activeField textRangeFromPosition:activeField.beginningOfDocument toPosition:activeField.endOfDocument]];
}

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

@end

第二个 .m 文件

#import "OTPTSaveViewController.h"
#import "OTPTAppDelegate.h"
#import "OTPTRecordViewController.h"

@interface OTPTSaveViewController () {
    UIViewController *parentViewController;
}

@end

@implementation OTPTSaveViewController

@synthesize textField;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    UITapGestureRecognizer *viewBackgroundTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(backgroundTap:)];
    viewBackgroundTap.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:viewBackgroundTap];
    parentViewController = [self presentingViewController];
}

- (IBAction)cancel:(id)sender {
    [[self navigationController] popViewControllerAnimated:YES];
}

- (IBAction)save:(id)sender {
    //some saving
}


- (BOOL)textFieldShouldReturn:(UITextField *)tf {
    [tf resignFirstResponder];
    return NO;
}

- (IBAction)backgroundTap:(id)sender
{
    [textField resignFirstResponder];
}

@end

我认为这个问题是因为来自弹出控制器的键盘通知。 但是当我添加

[self unregisterForKeyboardNotifications];

查看WillDisappear 并制作方法

- (void) unregisterForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];    
}

它对我没有任何影响

【问题讨论】:

  • “弹出到其他视图控制器”和“返回我的第一个视图”是什么意思?您应该提供更多信息,包括一些代码。
  • 显示你的.m文件的代码。

标签: ios iphone objective-c uiscrollview uinavigationcontroller


【解决方案1】:

从 iOS 7 开始,向 UIViewController 添加了一个新属性...

@property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets

根据Apple Docs:

默认值为 YES,它允许视图控制器调整其滚动视图插入以响应状态栏、导航栏和工具栏或选项卡栏所占用的屏幕区域。如果您想自己管理滚动视图插入调整,请设置为 NO,例如当视图层次结构中有多个滚动视图时。

如果您手动管理插图,您可能需要将此属性设置为 NO,因为这可能会干扰您尝试执行的操作。

【讨论】:

    【解决方案2】:

    我以某种狡猾的方式解决了这个问题

    我在 AppDelegate 中创建了一个名为 isAfterSafe 的 BOOL,在第二个文件中设置为 YES:

    - (void)textFieldDidBeginEditing:(UITextField *)textField
    {
        OTPTAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
        appDelegate.isAfterSave = YES;
    }
    

    并在第一个文件中使用简单的 if

    - (void)keyboardWasShown:(NSNotification*)aNotification
    {    
        OTPTAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
        if (!appDelegate.isAfterSave) {
            NSDictionary* info = [aNotification userInfo];
            CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    
            if (([holdOutTextField isEditing]) || ([cyclesTextField isEditing])) {
                UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height+50.0, 0.0);
                scrollView.contentInset = contentInsets;
                scrollView.scrollIndicatorInsets = contentInsets;
            }
    
            CGRect aRect = self.view.frame;
    
            aRect.size.height -= kbSize.height + self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height;
            CGPoint origin = activeField.frame.origin;
            origin.y -= scrollView.contentOffset.y;
            if (!CGRectContainsPoint(aRect, origin) ) {
                CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-(aRect.size.height));
                [scrollView setContentOffset:scrollPoint animated:YES];
            }
        }
        else appDelegate.isAfterSave = NO;    
    }
    

    当然,这不是一个漂亮的方法,但它解决了这个问题

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-03
      • 2019-07-03
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多