Остановить клавиатуру от скрытия UITextField при открытии - PullRequest
0 голосов
/ 11 февраля 2020

В поисках решения, которое предотвращает скрытие UITextField клавиатурой при его открытии независимо от того, где находится UITextField в иерархии представления и независимо от других элементов пользовательского интерфейса.

1 Ответ

0 голосов
/ 11 февраля 2020

В Интернете есть множество решений для настройки вида, чтобы UITextField не скрывался за клавиатурой при его появлении, однако я не смог найти решение типа «один размер подходит всем», поэтому пришлось много адаптировать ответов и сделать свой собственный. Это решение, которое я придумал. Надеюсь, это кому-нибудь поможет:)

Прежде всего, это решение предполагает, что ваше представление «первичного родителя» или «верхнего уровня» является UIScrollView или его потомком (например, UITableView или UICollectionView). Это не будет работать, если у вас нет UIScrollView в вашей иерархии, поскольку именно это используется для прокрутки UITextField в положение. Другие решения показывают, как прокручивать любой UIView, но когда вы думаете об этом, если вам нужно прокрутить UITextField в положение, скорее всего, ваш обзор должен быть прокручиваемым в любом случае, чтобы он не исчезал с экрана.

Создать метод расширения ниже. Это ищет подпредставления подпредставлений (et c.), Которые соответствуют данному запросу и возвращает их как массив. Мы будем использовать это позже.

public static UIView[] Find(this UIView view, Func<UIView, bool> query)
{
    if (view == null)
        return null;

    var views = new List<UIView>();

    if (query.Invoke(view))
        views.Add(view);

    foreach (var subview in view.Subviews)
    {
        var foundViews = subview.Find(query);

        if (foundViews != null)
            views.AddRange(foundViews);
    }

    return views.ToArray();
}

Добавьте приведенный ниже метод в свой UIViewController. Это находит UIScrollView верхнего уровня из иерархии представления. должен иметь только один результат.

private UIScrollView FindAdjustmentScrollView()
{
    var scrollViews = View.Find(v => v is UIScrollView && v.FindSuperviewOfType(View, typeof(UIScrollView)) == null);

    return scrollViews.Length > 0 ? scrollViews[0] as UIScrollView : null;
}

Добавить описанные ниже обработчики событий. Затем мы зарегистрируем их у наблюдателей.

private void Keyboard_Appear(NSNotification notification)
{
    var firstResponder = View.Find(v => v.IsFirstResponder).FirstOrDefault();

    var scrollView = FindAdjustmentScrollView();

    if (firstResponder == null || scrollView == null || !(notification.UserInfo[UIKeyboard.FrameEndUserInfoKey] is NSValue value))
        return;

    var keyboardBounds = value.CGRectValue;
    var firstResponderAbsoluteFrame = firstResponder.Superview.ConvertRectToView(firstResponder.Frame, View);

    // This is how much of a gap you would like there to be between the bottom of the UITextField
    // and the top of the keyboard. Not mandatory but a nice touch in my experience.
    var offset = 8;

    var bottom = firstResponderAbsoluteFrame.Y + firstResponderAbsoluteFrame.Height + offset;
    var scrollAmount = keyboardBounds.Height - (scrollView.Frame.Size.Height - bottom);

    if (scrollAmount > 0)
        scrollView.SetContentOffset(0, scrollView.ContentOffset.Y + scrollAmount);
}

private void Keyboard_Disappear(NSNotification notification)
{
    var firstResponder = View.Find(v => v.IsFirstResponder).FirstOrDefault();

    var scrollView = FindAdjustmentScrollView();

    if (firstResponder == null || scrollView == null)
        return;

    scrollView.SetContentOffset(0, 0);
}

Добавьте эти 2 поля в ваш UIViewController. Сохраняя ссылку на объект для наблюдателей, мы можем отменить их регистрацию позже, когда UIViewController больше не отображается.

private NSObject _keyboardWillShowObserver, _keyboardWillHideObserver;

В ViewWillAppear (или везде, где вы регистрируете свои обработчики событий) добавьте эти 2 строки. Они регистрируют наблюдателей и сохраняют ссылку на объект, чтобы мы могли отменить регистрацию позже.

_keyboardWillShowObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillShowNotification, Keyboard_Appear);
_keyboardWillHideObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillHideNotification, Keyboard_Disappear);

В ViewWillDisappear (или там, где вы отменяете регистрацию ваших обработчиков событий) добавьте эти 2 строки. Они отменяют регистрацию наблюдателей в UIViewController, поэтому они больше не отвечают на события.

NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardWillShowObserver);
NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardWillHideObserver);

Чтобы прояснить несколько вещей:

  • Это решение работает, когда ваш UITextField является подпредставлением многих слоев. down (даже UITableViewCell или UICollectionViewCell).
  • Это решение учитывает любые изменения, внесенные в представление клавиатуры. Например: если вы добавите кнопку «Готово» в верхней части клавиатуры, она будет рассчитана.
  • Настройка прокрутки анимирована.
  • Это решение работает в разных ориентациях.
...