Objective C: UIScroller и UItextfields, скрытые клавиатурой, появляются в UIViewController - PullRequest
3 голосов
/ 07 октября 2009

Мне нужна помощь, чтобы попытаться настроить в UIViewController клавиатуру: (a) не зависать над обоими полями UIText, поэтому скроллер должен быть расположен правильно; и (b) когда пользователь касается фона, клавиатура исчезает.

Я еще не пробовал (б), но пытаюсь (а), и код, который я получил от поиска в Google, не дал мне желаемого эффекта. Фактически, это заставляет мои текстовые поля исчезать, когда я касаюсь одного из них. Я уверен, что моя реализация activeField также неверна. Я получил этот пример из раздела Клавиатура Apple Development.

Код, который у меня есть, находится ниже:

@interface FirstViewController : UIViewController {
    IBOutlet UITextField *emailAddress;
    IBOutlet UITextField *password;
    IBOutlet UIButton *loginButton;
    IBOutlet UIScrollView *scroller;
    BOOL keyboardShown;
    UITextField *activeField;

    ASIHTTPRequest *requestRequiringAuthentication;
    ASINetworkQueue *networkQueue;
}

- (IBAction) LoginUser:(id)sender;

@property (nonatomic,retain) IBOutlet UITextField *emailAddress;
@property (nonatomic,retain) IBOutlet UITextField *password;
@property (nonatomic, retain) IBOutlet UIScrollView *scroller;
@property (nonatomic, retain) UITextField *activeField;
@property (retain) ASINetworkQueue *networkQueue;
@property (retain) ASIHTTPRequest *requestRequiringAuthentication;

@end


@implementation FirstViewController

@synthesize requestRequiringAuthentication;
@synthesize networkQueue;
@synthesize password;
@synthesize emailAddress;
@synthesize scroller;
@synthesize activeField;

#pragma mark -
#pragma mark LifeCycle

- (void)awakeFromNib
{
    NSLog(@"awaking from nib");
    [self setNetworkQueue:[[[ASINetworkQueue alloc] init] autorelease]];    
}    

- (void)viewDidLoad {
    NSLog(@"viewdidload");
    [super viewDidLoad];
}

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

- (void)viewWillAppear:(BOOL)animated {
    keyboardShown = NO;
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasHidden:) name:UIKeyboardDidHideNotification object:nil];
[super viewWillAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super viewWillDisappear:animated];
}


// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
    if (keyboardShown)
        return;

    NSDictionary* info = [aNotification userInfo];

    // Get the size of the keyboard.
    NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
    CGSize keyboardSize = [aValue CGRectValue].size;

    // Resize the scroll view (which is the root view of the window)
    CGRect viewFrame = [scroller frame];
    viewFrame.size.height -= keyboardSize.height;
    scroller.frame = viewFrame;

    // Scroll the active text field into view.
    CGRect textFieldRect = [activeField frame];
    [scroller scrollRectToVisible:textFieldRect animated:YES];

    keyboardShown = YES;
}

// Called when the UIKeyboardDidHideNotification is sent
- (void)keyboardWasHidden:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];

    // Get the size of the keyboard.
    NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
    CGSize keyboardSize = [aValue CGRectValue].size;

    // Reset the height of the scroll view to its original value
    CGRect viewFrame = [scroller frame];
    viewFrame.size.height += keyboardSize.height;
    scroller.frame = viewFrame;

    keyboardShown = NO;
}

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

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

Ответы [ 4 ]

3 голосов
/ 07 октября 2009

Я нашел следующий код в записи блога (я не знаю, какой именно, потому что я думаю, что он был сохранен в NNW до перехода на синхронизацию с Google Reader). Все это находится в файле реализации, просто сделайте ваш класс делегатом для ваших UITextFields и объявите его как соответствующий протоколу UITextFieldDelegate в вашем заголовке. Я вытащил это прямо из кода для одного из моих приложений доставки, и он отлично работает для перемещения текстовых полей с клавиатуры. Я еще не настроил ваш (B), но я считаю, что это просто еще один метод UITextFieldDelegate, который необходимо реализовать.

Установите следующие константы для вашего класса:

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 = 140;

А затем добавьте эти два метода:

- (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);
    }
    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];
}
0 голосов
/ 09 мая 2013

Правильный код:

 static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
 static const CGFloat MINIMUM_SCROLL_FRACTION = 0.0;
 static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.2;
 static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
 static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 240;

- (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);
  }
  heightFraction = numerator / denominator;

  if (heightFraction < 0.0)
  {
    heightFraction = 0.0;
  }
  else if (heightFraction > 1.0)
  {
    heightFraction = 1.0;
  }

  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];
}

Настройте статические константы в соответствии с вашими потребностями.

0 голосов
/ 05 октября 2010

Я искал что-то подобное в моем случае, когда поле пароля было скрыто клавиатурой. Я хотел решить мою проблему с минимальным количеством строк кода.

Это решение может также работать с несколькими текстовыми полями, но просто определить каждое поле и применить необходимое смещение.

В моем случае

1) Сначала я поместил имя пользователя, пароль и кнопку входа в scrollView.

2) Сделал viewController UITextFieldDelegate

3) Написал следующие строки кода (убедитесь, что ваш scrollView является IBOutlet и подключен из Interface Builder)

- (void)textFieldDidBeginEditing:(UITextField *)textField 
{
    if ([textField isEqual:textAccountPassword] == NO)
        return;

    CGPoint bottomOffset = CGPointMake(0, 20);
    [scrollview setContentOffset: bottomOffset animated: YES];
}


- (void)textFieldDidEndEditing:(UITextField *)textField 
{
    CGPoint bottomOffset = CGPointMake(0, 0); // return it back to no offset
    [scrollview setContentOffset: bottomOffset animated: YES];
}
0 голосов
/ 07 октября 2009

Я думаю, что самый простой способ решить эту проблему - сдвинуть изображение вверх и вниз в соответствии с клавиатурой

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    CGRect rect = self.view.frame;
    rect = CGRectMake(rect.origin.x, rect.origin.y,
                  rect.size.width, rect.size.height + 80);//keyboard height
    [UIView beginAnimations: @"anim" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    self.view.frame = rect;
    [UIView commitAnimations];
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    //same as above but you shift it down
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...