В Интернете есть множество решений для настройки вида, чтобы 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).
- Это решение учитывает любые изменения, внесенные в представление клавиатуры. Например: если вы добавите кнопку «Готово» в верхней части клавиатуры, она будет рассчитана.
- Настройка прокрутки анимирована.
- Это решение работает в разных ориентациях.