Подтвердить что ты не робот

Уклонение UIKeyboard и автоматическая компоновка

Учитывая акцент на Auto Layout в iOS 6 и рекомендацию инженеров Apple (см. видеоролики WWDC 2012), мы больше не будем манипулировать рамками представлений, как бы избежать использования клавиатуры, используя только автоматический макет и NSLayoutConstraint

Обновление

Это выглядит как разумное решение: Пример клавиатуры с учетом клавиатуры (Источник GitHub), но одна потенциальная проблема, которую я вижу, - это то, что происходит, когда пользователь поворачивает устройство, а клавиатура уже находится на экране?

4b9b3361

Ответ 1

Моя идея - создать UIView, разрешить вызов клавиатуры и поместить его в режим просмотра контроллера. Затем наблюдайте уведомления об изменении рамки клавиатуры UIKeyboardDidChangeFrameNotification и сопоставьте кадр клавиатуры с видом клавиатуры (я рекомендую анимировать изменение). Наблюдение за этим уведомлением обрабатывает упомянутое вращение, а также перемещает клавиатуру на iPad.

Затем просто создайте свои ограничения относительно этого вида клавиатуры. Не забудьте добавить ограничение в общий просмотр.

Чтобы правильно преобразовать и повернуть рамку клавиатуры в координаты вашего просмотра, проверьте документы для UIKeyboardFrameEndUserInfoKey.

Ответ 2

Это сообщение в блоге замечательно, но я хотел бы предложить некоторые улучшения. Во-первых, вы можете зарегистрироваться, чтобы наблюдать изменения кадров, поэтому вам не нужно регистрироваться, чтобы наблюдать как шоу, так и скрывать уведомления. Во-вторых, вы должны преобразовать CGR для клавиатуры с экрана для просмотра координат. Наконец, вы можете скопировать точную кривую анимации, используемую iOS для самой клавиатуры, поэтому клавиатура и представления отслеживания перемещаются синхронно.

Объединяя все это, вы получаете следующее:

@interface MyViewController ()
// This IBOutlet holds a reference to the bottom vertical spacer
// constraint that positions the "tracking view",i.e., the view that
// we want to track the vertical motion of the keyboard
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomVerticalSpacerConstraint;
@end


@implementation MyViewController
-(void)viewDidLoad
{
  [super viewDidLoad];
  // register for notifications about the keyboard changing frame
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(keyboardWillChangeFrame:)
                                               name:UIKeyboardWillChangeFrameNotification
                                             object:self.view.window];
}

-(void)keyboardWillChangeFrame:(NSNotification*)notification
{
  NSDictionary * userInfo = notification.userInfo;
  UIViewAnimationCurve animationCurve  = [userInfo[UIKeyboardAnimationCurveUserInfoKey] intValue];
  NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];

  // convert the keyboard CGRect from screen coords to view coords
  CGRect kbEndFrame = [self.view convertRect:[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]
                                    fromView:self.view.window];
  CGRect kbBeginFrame = [self.view convertRect:[[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue]
                                      fromView:self.view.window];
  CGFloat deltaKeyBoardOrigin = kbEndFrame.origin.y - kbBeginFrame.origin.y;

  // update the constant factor of the constraint governing your tracking view
  self.bottomVerticalSpacerConstraint.constant -= deltaKeyBoardOrigin;
  // tell the constraint solver it needs to re-solve other constraints.
  [self.view setNeedsUpdateConstraints];

  [UIView beginAnimations:nil context:NULL];
  [UIView setAnimationDuration:duration];
  [UIView setAnimationCurve:animationCurve];
  [UIView setAnimationBeginsFromCurrentState:YES];
  // within this animation block, force the layout engine to apply 
  // the new layout changes immediately, so that we
  // animate to that new layout. We need to use old-style
  // UIView animations to pass the curve type.
  [self.view layoutIfNeeded];
  [UIView commitAnimations];
}

-(void)dealloc {
  [[NSNotificationCenter defaultCenter] removeObserver:self
                                                  name:UIKeyboardWillChangeFrameNotification
                                                object:nil];
}
@end

Это будет работать, если вы не измените ориентацию, когда клавиатура вставлена.

Это был ответ на Как подражать анимации клавиатуры на iOS 7 для добавления "Готово" на цифровую клавиатуру? показал, как правильно имитировать кривую анимации клавиатуры.

Последнее, что следует опасаться в отношении всех этих решений на основе уведомлений: они могут создавать неожиданные эффекты, если какой-либо другой экран в вашем приложении также использует клавиатуру, потому что ваш контроллер просмотра все равно получит уведомления, если он не освобождается, даже если он просматривается, выгружается. Одним из средств для этого является установка условного обозначения в обработчике уведомлений, чтобы убедиться, что он работает только при отображении на экране контроллера вида.

Ответ 3

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

@interface YMKeyboardLayoutHelperView ()
@property (nonatomic) CGFloat desiredHeight;
@property (nonatomic) CGFloat duration;
@end

@implementation YMKeyboardLayoutHelperView

- (id)init
{
    self = [super init];
    if (self) {
        self.translatesAutoresizingMaskIntoConstraints = NO;

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:@"UIKeyboardWillShowNotification" object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:@"UIKeyboardWillHideNotification" object:nil];
    }
    return self;
}

- (void)keyboardWillShow:(NSNotification *)notification
{
    // Save the height of keyboard and animation duration
    NSDictionary *userInfo = [notification userInfo];
    CGRect keyboardRect = [userInfo[@"UIKeyboardBoundsUserInfoKey"] CGRectValue];
    self.desiredHeight = CGRectGetHeight(keyboardRect);
    self.duration = [userInfo[@"UIKeyboardAnimationDurationUserInfoKey"] floatValue];

    [self setNeedsUpdateConstraints];
}

- (void)keyboardWillHide:(NSNotification *)notification
{
    // Reset the desired height (keep the duration)
    self.desiredHeight = 0.0f;

    [self setNeedsUpdateConstraints];
}

- (void)updateConstraints
{
    [super updateConstraints];

    // Remove old constraints
    if ([self.constraints count]) {
        [self removeConstraints:self.constraints];
    }

    // Add new constraint with desired height
    NSString *constraintFormat = [NSString stringWithFormat:@"V:[self(%f)]", self.desiredHeight];
    [self addVisualConstraints:constraintFormat views:@{@"self": self}];

    // Animate transition
    [UIView animateWithDuration:self.duration animations:^{
        [self.superview layoutIfNeeded];
    }];

}

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

@end

Ответ 4

Используя KeyboardLayoutConstraint в Spring framework - самое простое решение, которое я нашел до сих пор. KeyboardLayoutConstraint

Ответ 5

Ive написал библиотеку, которая сделает все это за вас (поддерживает автоматическую компоновку и пружины и Struts)

IHKeyboardAvoiding https://github.com/IdleHandsApps/IHKeyboardAvoiding

Просто вызовите [IHKeyboardAvoiding setAvoidingView: self.myView];

Ответ 6

Для автоматической компоновки с корпусом клавиатуры я использую статический вид таблицы. Это значительно упрощает ваши коды и не требует отслеживания высоты клавиатуры. Одна вещь, которую я узнал о представлении таблицы, состоит в том, чтобы сохранить каждую таблицу как можно более узкой. Если вы помещаете слишком много пользовательских интерфейсов вертикально в одну строку, вы можете получить перекрытие клавиатуры.