2012-01-02 3 views
36

Я знаю, что этот вопрос задавали снова и снова, но мне кажется, что ничего не работает. Большинство решений вокруг довольно устарели, а остальные - невероятно огромные блоки кода, которые в десять раз больше, чем собственно кодирование проектов. У меня есть несколько UITextFields, выстроенных вертикально, но когда клавиатура запускает для редактирования, она закрывает текстовое поле. Мне было интересно, есть ли простой новичок, чтобы прокрутить представление вверх, а затем отступить, когда начинается и заканчивается редактирование?Как прокрутить вверх, когда появляется клавиатура?

спасибо.

+0

возможно дубликат [Как сделать UITextField двигаться вверх, когда клавиатура присутствует] (http://stackoverflow.com/questions/1126726/how-to-make-a-uitextfield-move-up-when -keyboard-is-present) –

ответ

28

Я разработал решения, которые работают со списком прокрутки и без прокрутки с помощью уведомления клавиатуры и обнаружения текущего первого ответчика, но иногда я использую это тривиальное решение: простой способ - обнаружить открытую клавиатуру через текст полевого делегата textViewDidBeginEditing: и переместить весь вид вверх. Самый простой способ сделать это - это что-то вроде изменения self.view.bounds.origin.y -100 (или что-то еще). Используйте соответствующий метод textViewShouldEndEditing:, чтобы установить его на противоположное, что в этом случае равно 100. Изменение bounds является относительной процедурой. После его изменения кадр перемещается, но начало координат по-прежнему равно нулю.

+6

Спасибо. Это мой код: '- (BOOL) textViewDidBeginEditing: (UITextField *) textField { [UIView beginAnimations: nil context: NULL]; [UIView setAnimationDuration: 0.35f]; CGRect frame = self.view.frame; frame.origin.y = -100; [self.view setFrame: frame]; [UIView commitAnimations]; } 'Но я получаю предупреждение о том, что« Control достигает конца не-void функции ». Я не уверен, как обойти это, извините, я все еще новичок в этом. – John

+1

np. Добавьте 'return YES;' в конце метода, чтобы сказать, что вы разрешаете редактирование. Не забудьте установить этот класс в качестве делегата для этого текстового представления. Существует соответствующий метод для UITextFieldDelegates, называемый 'textFieldDidBeginEditing:', если вам нужно. –

+0

Удивительный, это и трюк, спасибо большое. Еще один вопрос: как установить этот класс в качестве делегата для этого текстового представления? Извините, если его немой вопрос lol. – John

24

Поскольку я нашел его, я использую TPKeyboardAvoiding - https://github.com/michaeltyson/TPKeyboardAvoiding.

Это работает прекрасно, и очень прост в установке:

  • Добавить UIScrollView в XIb ваш взгляд контроллера
  • Установите класс мнение, скроллинга к TPKeyboardAvoidingScrollView (еще в XIb, с помощью инспектора идентичности)
  • Поместите все ваши средства управления в пределах этой точки зрения прокрутки

вы также можете создать его программно, если вы хотите.


Существует класс для такой же потребности внутри UITableViewController; это необходимо только в том случае, если вы поддерживаете версию iOS ниже 4.3.

+0

Прохладный, спасибо, я собираюсь попробовать это сейчас. Это может быть глупым вопросом, но я уже настроил nib, добавит ли прокрутка на вершине пиджака вообще? (Я также установил фон в Image View) – John

+0

Просто добавьте представление в nib, а затем переместите другие элементы внутри представления. Все ваши свойства элементов (IBOutlet, конфигурация) будут сохранены. Если вы перепутали, отмените последний шаг (или вернитесь к последнему фиксации!) – Guillaume

+0

, если библиотека выполнена Micheal Tyson, то я использую ее. Просто. – abbood

-1

У меня есть scrollview и 3 текстовых поля в этом. У меня есть простой код из моего собственного приложения:

.h файл является:

#import <UIKit/UIKit.h> 

@interface AddContactViewController : UIViewController<UITextFieldDelegate, UIScrollViewDelegate> 

@property (nonatomic, retain) NSDictionary *dict_contactDetail; 

@property (nonatomic, retain) IBOutlet UILabel *lbl_name; 
@property (nonatomic, retain) IBOutlet UITextField *txtField_tel; 
@property (nonatomic, retain) IBOutlet UITextField *txtField_address; 
@property (nonatomic, retain) IBOutlet UITextField *txtField_email; 

@property (nonatomic, retain) IBOutlet UIScrollView *scrollView; 

@end 

.m файл:

#import "AddContactViewController.h" 

@interface AddContactViewController() 

@end 

@implementation AddContactViewController 

@synthesize dict_contactDetail; 

@synthesize lbl_name, txtField_tel, txtField_email, txtField_address, scrollView; 

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

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view from its nib. 

    // NSLog(@"dict_contactDetail : %@", dict_contactDetail); 

    UIBarButtonItem * rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Add" style:UIBarButtonSystemItemDone target:self action:@selector(addEmergencyContact:)]; 
    self.navigationItem.rightBarButtonItem = rightButton; 


    lbl_name.text = [NSString stringWithFormat:@"%@ %@", [dict_contactDetail valueForKey:@"fname"], [dict_contactDetail valueForKey:@"lname"]]; 

    txtField_tel.returnKeyType = UIReturnKeyDone; 
    txtField_email.returnKeyType = UIReturnKeyDone; 
    txtField_address.returnKeyType = UIReturnKeyDone; 

} 



-(void)addEmergencyContact:(id)sender 
{ 
    scrollView.frame = CGRectMake(0, 0, 320, 460); 
} 

#pragma mark - text field delegates 
- (void)textFieldDidBeginEditing:(UITextField *)textField 
{ 
    if([textField isEqual:txtField_tel]) 
    { 
     [scrollView setContentOffset:CGPointMake(0, 70)]; 
     scrollView.frame = CGRectMake(0, 0, 320, 210); 
    } 
    if([textField isEqual:txtField_address]) 
    { 
     [scrollView setContentOffset:CGPointMake(0, 140)]; 
     scrollView.frame = CGRectMake(0, 0, 320, 210); 
    } 
    if([textField isEqual:txtField_email]) 
    { 
     [scrollView setContentOffset:CGPointMake(0, 210)]; 
     scrollView.frame = CGRectMake(0, 0, 320, 210); 
    } 
} 

- (BOOL)textFieldShouldReturn:(UITextField *)textField 
{ 
    scrollView.frame = CGRectMake(0, 0, 320, 460); 
    [textField resignFirstResponder]; 
    return YES; 
} 



@end 
1

Я потратил некоторое время на эту проблему и собрал штук код, чтобы создать один окончательное решение. Моя проблема связана с прокруткой UITableView и открытием/закрытием клавиатуры.

Вам нужны два частичных методы в классе клеток:

void EditingBegin(UITextField sender) 
    { 
     // Height of tallest cell, you can ignore this! 
     float tableMargin = 70.0f; 
     float tableHeight = _tableView.Frame.Size.Height; 
     float keyBoardHeight = KeyboardHeight(); 

     NSIndexPath[] paths = this._tableView.IndexPathsForVisibleRows; 
     RectangleF rectLast = this._tableView.RectForSection(paths[paths.Length - 1].Section); 
     RectangleF rectFirst = this._tableView.RectForSection(paths[0].Section); 
     float lastCellY = rectLast.Y - rectFirst.Y; 
     if (lastCellY > tableHeight - keyBoardHeight) 
     { 
      float diff = lastCellY - (tableHeight - tableMargin - keyBoardHeight); 
      this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f); 
     } 

     float cellPosition = this._tableView.RectForSection(this._section).Y; 
     if (cellPosition > tableHeight - keyBoardHeight) 
     { 
      if (this._tableView.ContentInset.Bottom == 0.0f) 
      { 
       float diff = cellPosition - (tableHeight - tableMargin - keyBoardHeight); 
       this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f); 
      } 
      else 
      { 
       this._tableView.ScrollToRow(NSIndexPath.FromItemSection(0, this._section), UITableViewScrollPosition.Middle, true); 
      } 
     } 
    } 

    partial void EditingEnd(UITextField sender) 
    { 
     UIView.BeginAnimations(null); 
     UIView.SetAnimationDuration(0.3f); 
     this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, 0.0f, 0.0f); 
     UIView.CommitAnimations(); 
    } 

, а затем в классе контроллера представления:

public override void WillAnimateRotation(UIInterfaceOrientation toInterfaceOrientation, double duration) 
    { 
     base.WillAnimateRotation(toInterfaceOrientation, duration); 

     float bottom = this.TableView.ContentInset.Bottom; 
     if (bottom > 0.0f) 
     { 
      if (toInterfaceOrientation == UIInterfaceOrientation.Portrait || toInterfaceOrientation == UIInterfaceOrientation.PortraitUpsideDown) 
      { 
       bottom = bottom * UIScreen.MainScreen.Bounds.Width/UIScreen.MainScreen.Bounds.Height; 
      } 
      else 
      { 
       bottom = bottom * UIScreen.MainScreen.Bounds.Height/UIScreen.MainScreen.Bounds.Width; 
      } 

      UIEdgeInsets insets = this.TableView.ContentInset; 
      this.TableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, bottom, 0.0f); 
     } 
    } 
0

Если у вас есть UITableView или UIScrollView, лучше изменить значение contentOffset вместо внесения изменений в frame.

Работа на Peter's Answer, добавив этот метод вашего класса работает хорошо:

- (void)textViewDidBeginEditing:(UITextField *)textField { 
    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.35f]; 
    CGPoint offset = self.tableView.contentOffset; 
    offset.y += 200; // You can change this, but 200 doesn't create any problems 
    [self.tableView setContentOffset:offset]; 
    [UIView commitAnimations]; 
} 

Вот так, нет необходимости, чтобы добавить метод textViewDidEndEditing.


мне не нужно говорить об этом, но для этого, чтобы работать ваш UITextField или UITextViewдолжен быть делегатом вашего контроллера.

3

@BenLu и другие пользователи, которые сталкиваются с проблемой функции никогда не вызывались из-за следующие причинами: В качестве функции bydefaults делегата inbuild возвращается тщетным вместо BOOL это то, как оно должно выглядеть следующим образом:

-(void)textFieldDidBeginEditing:(UITextField *)textField 
{ 
    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.35f]; 
    CGRect frame = self.view.frame; 
    frame.origin.y = -100; 
    [self.view setFrame:frame]; 
    [UIView commitAnimations]; 
} 

-(void)textFieldDidEndEditing:(UITextField *)textField 
{ 
    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.35f]; 
    CGRect frame = self.view.frame; 
    frame.origin.y = 100; 
    [self.view setFrame:frame]; 
    [UIView commitAnimations]; 
} 
0

Начиная с ответа Питера, я разработал следующий подход в Swift 3.0 под iOS 10.1. Я делаю это для textView, поэтому я реализовал функции UITextViewDelegate textViewDidBeginEditing и textViewDidEndEditing, где я корректирую границы представления. Как вы можете видеть, я устанавливаю значение начала Y для небольшого положительного числа для прокрутки вверх, а затем обратно в 0, чтобы вернуться в исходное положение.

Вот соответствующий код моего ViewController. Вам не нужно анимировать, но это добавляет приятный штрих.

func textViewDidBeginEditing(_ textView: UITextView) 
{ 
    if UIScreen.main.bounds.height < 568 { 
     UIView.animate(withDuration: 0.75, animations: { 
      self.view.bounds.origin.y = 60 
     }) 
    } 
} 

func textViewDidEndEditing(_ textView: UITextView) 
{ 
    if UIScreen.main.bounds.height < 568 { 
     UIView.animate(withDuration: 0.75, animations: { 
      self.view.bounds.origin.y = 0 
     }) 
    } 
} 
Смежные вопросы