当UITextField模糊UITextField时,如何正确实现将UITextFields转移到用户输入之上的功能?

时间:2018-01-26 11:33:49

标签: ios objective-c uiscrollview uitextfield

找到了UITextFields的{​​{1}}的Apple文档,其中详细说明了如何制作该文档,以便UITextField内的UIScrollView可以向上移动,以便用户可以查看他们的输入。但是,每当我尝试实现它时,行为都不会如所描述的那样。无论您选择编辑哪个UITextField,它都不会执行任何操作或将所有内容向下移动。

这是我的代码,有人可以诊断它吗?:

#import "FourthViewController.h"
@import Firebase;
@import FirebaseAuth;
@import FirebaseDatabase;

@interface FourthViewController ()
{
    UITextField *activeField;
}
@property (strong, nonatomic) FIRDatabaseReference *ref;
@property (weak, nonatomic) IBOutlet UIButton *logoutButton;
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (readonly, nonatomic, nullable) FIRApp *app;
@property (readonly, strong, nonatomic, nullable) FIRUser *currentUser;
@property(weak, nonatomic) NSArray *countryArray;
@property (weak, nonatomic) IBOutlet UITextField *usernameEntry;
@property (weak, nonatomic) IBOutlet UITextField *forenameEntry;
@property (weak, nonatomic) IBOutlet UITextField *surnameEntry;
@property (weak, nonatomic) IBOutlet UITextField *emailAddressEntry;
@property (weak, nonatomic) IBOutlet UITextField *countryEntry;
@property (weak, nonatomic) IBOutlet UITextField *homeAddressEntry;
@property (weak, nonatomic) IBOutlet UIButton *applyChangesButton;
@property (weak, nonatomic) IBOutlet UIImageView *profilePictureEntry;
@property (weak, nonatomic) IBOutlet UILabel *emailValidationCheck;
@property (weak, nonatomic) IBOutlet UIPickerView *countrySelector;


@end

@implementation FourthViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.ref = [[FIRDatabase database] reference];
    FIRUser *user = [FIRAuth auth].currentUser;

    if (user)
    {
        [[[[_ref child: @"Users"] child:user.uid] child:@"Username"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot)
        {
            if (snapshot.exists)
            {
                _usernameEntry.text = snapshot.value;
            }
        }];

        _emailAddressEntry.text = user.email;
    }

    _countrySelector.delegate = self;
    _countrySelector.dataSource = self;

    self.logoutButton.layer.cornerRadius= 8;
    self.logoutButton.layer.borderWidth = 1.5f;
    self.logoutButton.layer.borderColor = [UIColor whiteColor].CGColor;
    [_logoutButton addTarget:self action:@selector(logoutButtonHighlightBorder) forControlEvents:UIControlEventTouchDown];
    [_logoutButton addTarget:self action:@selector(logoutButtonUnhighlightBorder) forControlEvents:UIControlEventTouchUpInside];
    [_logoutButton addTarget:self action:@selector(logoutButtonUnhighlightBorder) forControlEvents:UIControlEventTouchDragExit];

    self.applyChangesButton.layer.cornerRadius = 8;

    _countrySelector.layer.cornerRadius = 8;

    NSLocale *locale = [NSLocale currentLocale];

    NSArray *countryArray = [NSLocale ISOCountryCodes];
    NSMutableArray *sortedCountryArray = [[NSMutableArray alloc] init];
    for (NSString *countryCode in countryArray)
    {
        NSString *displayNameString = [locale displayNameForKey:NSLocaleCountryCode value:countryCode];
        [sortedCountryArray addObject:displayNameString];
    }
    [sortedCountryArray sortUsingSelector:@selector(localizedCompare:)];
}


- (IBAction)applyChanges:(UIButton *)sender
{
    NSString *userID = [FIRAuth auth].currentUser.uid;
    NSString* username = _usernameEntry.text;
    [[[_ref child:@"Users"] child:userID] setValue:@{@"Username": username}];

    [[FIRAuth auth].currentUser updateEmail:_emailAddressEntry.text
                             completion:^(NSError * _Nullable error)
     {
         if(error)
         {
             [_emailValidationCheck setTextColor:[UIColor redColor]];
             _emailValidationCheck.text = @"Email Address modification was unsuccessful";
         }
         else
         {
             [_emailValidationCheck setTextColor:[UIColor greenColor]];
             _emailValidationCheck.text = @"Email Address modification was successful";
         }
     }];
}

- (IBAction)logout:(UIButton *)sender
{
    NSError *signOutError;
    BOOL status = [[FIRAuth auth] signOut:&signOutError];
    if (!status)
    {
        NSLog(@"Error signing out: %@", signOutError);
    }
    else
    {
        NSLog(@"Successfully Signout");
    }
}

- (NSInteger)numberOfComponentsInPickerView:(nonnull UIPickerView *)pickerView
{
    return 1;
}

- (NSInteger)pickerView:(nonnull UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    return _countryArray.count;
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    return _countryArray[row];
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    _countryEntry.text = _countryArray[row];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

- (void)logoutButtonHighlightBorder
{
    _logoutButton.layer.borderColor = [UIColor colorWithRed:0.61 green:0.00 blue:0.02 alpha:1.0].CGColor;
}

- (void)logoutButtonUnhighlightBorder
{
    _logoutButton.layer.borderColor = [UIColor whiteColor].CGColor;
}

- (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:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    CGRect bkgndRect = activeField.superview.frame;
    bkgndRect.size.height += kbSize.height;
    [activeField.superview setFrame:bkgndRect];
    [_scrollView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height) animated:YES];
}

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;
}

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

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

更新代码:

#import "FourthViewController.h"
@import Firebase;
@import FirebaseAuth;
@import FirebaseDatabase;

@interface FourthViewController ()
{
    UITextField *activeField;
}
@property (strong, nonatomic) FIRDatabaseReference *ref;
@property (weak, nonatomic) IBOutlet UIButton *logoutButton;
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (readonly, nonatomic, nullable) FIRApp *app;
@property (readonly, strong, nonatomic, nullable) FIRUser *currentUser;
@property(weak, nonatomic) NSArray *countryArray;
@property (weak, nonatomic) IBOutlet UITextField *usernameEntry;
@property (weak, nonatomic) IBOutlet UITextField *forenameEntry;
@property (weak, nonatomic) IBOutlet UITextField *surnameEntry;
@property (weak, nonatomic) IBOutlet UITextField *emailAddressEntry;
@property (weak, nonatomic) IBOutlet UITextField *countryEntry;
@property (weak, nonatomic) IBOutlet UITextField *homeAddressEntry;
@property (weak, nonatomic) IBOutlet UIButton *applyChangesButton;
@property (weak, nonatomic) IBOutlet UIImageView *profilePictureEntry;
@property (weak, nonatomic) IBOutlet UILabel *emailValidationCheck;
@property (weak, nonatomic) IBOutlet UIPickerView *countrySelector;


@end

@implementation FourthViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.ref = [[FIRDatabase database] reference];
    FIRUser *user = [FIRAuth auth].currentUser;

    [self registerForKeyboardNotifications];

    if (user)
    {
        [[[[_ref child: @"Users"] child:user.uid] child:@"Username"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot)
        {
            if (snapshot.exists)
            {
                _usernameEntry.text = snapshot.value;
            }
        }];

        _emailAddressEntry.text = user.email;
    }

    _countrySelector.delegate = self;
    _countrySelector.dataSource = self;

    self.logoutButton.layer.cornerRadius= 8;
    self.logoutButton.layer.borderWidth = 1.5f;
    self.logoutButton.layer.borderColor = [UIColor whiteColor].CGColor;
    [_logoutButton addTarget:self action:@selector(logoutButtonHighlightBorder) forControlEvents:UIControlEventTouchDown];
    [_logoutButton addTarget:self action:@selector(logoutButtonUnhighlightBorder) forControlEvents:UIControlEventTouchUpInside];
    [_logoutButton addTarget:self action:@selector(logoutButtonUnhighlightBorder) forControlEvents:UIControlEventTouchDragExit];

     self.applyChangesButton.layer.cornerRadius = 8;

    _countrySelector.layer.cornerRadius = 8;

     NSLocale *locale = [NSLocale currentLocale];

     NSArray *countryArray = [NSLocale ISOCountryCodes];
     NSMutableArray *sortedCountryArray = [[NSMutableArray alloc] init];
     for (NSString *countryCode in countryArray)
    {
        NSString *displayNameString = [locale displayNameForKey:NSLocaleCountryCode value:countryCode];
        [sortedCountryArray addObject:displayNameString];
    }
    [sortedCountryArray sortUsingSelector:@selector(localizedCompare:)];
}


- (IBAction)applyChanges:(UIButton *)sender
{
    NSString *userID = [FIRAuth auth].currentUser.uid;
    NSString* username = _usernameEntry.text;
    [[[_ref child:@"Users"] child:userID] setValue:@{@"Username": username}];

    [[FIRAuth auth].currentUser updateEmail:_emailAddressEntry.text
                             completion:^(NSError * _Nullable error)
     {
         if(error)
         {
             [_emailValidationCheck setTextColor:[UIColor redColor]];
             _emailValidationCheck.text = @"Email Address modification was unsuccessful";
         }
         else
         {
             [_emailValidationCheck setTextColor:[UIColor greenColor]];
             _emailValidationCheck.text = @"Email Address modification was successful";
         }
     }];
}

- (IBAction)logout:(UIButton *)sender
{
    NSError *signOutError;
    BOOL status = [[FIRAuth auth] signOut:&signOutError];
    if (!status)
    {
        NSLog(@"Error signing out: %@", signOutError);
    }
    else
    {
        NSLog(@"Successfully Signout");
    }
}

- (NSInteger)numberOfComponentsInPickerView:(nonnull UIPickerView *)pickerView
{
    return 1;
}

- (NSInteger)pickerView:(nonnull UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    return _countryArray.count;
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    return _countryArray[row];
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    _countryEntry.text = _countryArray[row];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

- (void)logoutButtonHighlightBorder
{
    _logoutButton.layer.borderColor = [UIColor colorWithRed:0.61 green:0.00 blue:0.02 alpha:1.0].CGColor;
}

- (void)logoutButtonUnhighlightBorder
{
    _logoutButton.layer.borderColor = [UIColor whiteColor].CGColor;
}

- (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];
    CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat offset = CGRectGetMaxY(activeField.frame) - CGRectGetMinY(kbFrame);
    [_scrollView setContentOffset:CGPointMake(0.0, offset) animated:YES];
}

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;
}

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

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

@end

1 个答案:

答案 0 :(得分:0)

您要做的是将textField的下边缘直接移到键盘上方。这是通过正确调整scrollView的contentOffset来完成的。你已经看到了几乎正确的事情。唯一可能出错的是你改变CGRect bkgndRect = activeField.superview.frame;不必要的东西。您可以尝试以下方法,其中minY / maxY是frame.origin.y /(frame.origin.y + frame.size.height)。

- (void)keyboardWillShow:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat offset = CGRectGetMaxY(activeTextField.frame) - CGRectGetMinY(kbFrame)
    _scrollView.contentOffset = CGPointMake(0.0, offset);
}

- (void)keyboardWillHide:(NSNotification*)aNotification
{
    _scrollView.contentOffset = CGPointZero;
}

此外,您还可以检查计算的偏移量是否> 0,因为在这种情况下,文本字段已经在键盘上方。

当键盘被隐藏时,我想我从来没有更新滚动指示器插图。只需重置滚动视图的内容偏移量即可。

如果有一天你需要这个代码用于Swift 4 ++ - 这里也是一个例子,不使用自动布局。实际上,我测试了这段代码并且有效:

class ViewController: UIViewController {

    var willShow: NSObjectProtocol?
    var willHide: NSObjectProtocol?

    let scroll = UIScrollView()
    let txt = UITextField()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white


        scroll.frame = view.bounds
        scroll.translatesAutoresizingMaskIntoConstraints = true
        view.addSubview(scroll)

        txt.frame = CGRect(x: 0, y: scroll.bounds.height-100, width: scroll.bounds.width, height: 50)
        txt.text = "Hello World"
        txt.backgroundColor = .lightGray
        txt.translatesAutoresizingMaskIntoConstraints = true
        scroll.addSubview(txt)

        willShow = NotificationCenter.default.addObserver(forName: .UIKeyboardWillShow, object: nil, queue: .main) { (note) in
            let kbFrame = note.userInfo?[UIKeyboardFrameEndUserInfoKey] as? CGRect ?? .zero
            self.scroll.contentOffset = CGPoint(x: 0, y: self.txt.frame.maxY - kbFrame.minY )
        }

        willHide = NotificationCenter.default.addObserver(forName: .UIKeyboardWillHide, object: nil, queue: .main) { (note) in
            self.scroll.contentOffset = .zero
        }

        view.addGestureRecognizer(UITapGestureRecognizer(target: txt, action: #selector(resignFirstResponder)))
    }
}

希望有所帮助