阻止键盘在打开时隐藏 UITextField
Stop Keyboard From Hiding UITextField When Open
寻找一种解决方案,阻止 UITextField 在打开时被键盘隐藏,而不管 UITextField 在视图层次结构中的哪个位置,也不管其他 UI 元素。
在线有很多解决方案可以调整您的视图,这样 UITextField 在出现时就不会隐藏在键盘后面,但是,我找不到 "one size fits all" 种解决方案,因此不得不采用很多答案,然后自己做。这是我想出的解决方案。希望它对某人有所帮助:)
首先,此解决方案假定您的 "primary parent" 或 "top level" 视图是 UIScrollView 或后代(例如 UITableView 或 UICollectionView)。如果您的层次结构中没有 UIScrollView,这将不起作用,因为这是用于将 UITextField 滚动到位的。其他解决方案向您展示了如何滚动任何 UIView,但是当您考虑它时,如果您需要将 UITextField 滚动到位,您的视图可能无论如何都应该是可滚动的以阻止它离开屏幕。
在下面创建扩展方法。这将搜索与给定查询匹配的子视图(等)的子视图,并将它们 returns 作为数组。我们稍后会用到它。
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(或您注册事件处理程序的任何地方)中添加这两行。这些注册观察者并保留一个对象引用,以便我们稍后可以取消注册。
_keyboardWillShowObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillShowNotification, Keyboard_Appear);
_keyboardWillHideObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillHideNotification, Keyboard_Disappear);
在 ViewWillDisappear(或您注销事件处理程序的任何地方)中添加这两行。这些从 UIViewController 取消注册观察者,因此他们不再响应事件。
NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardWillShowObserver);
NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardWillHideObserver);
澄清一些事情:
- 当您的 UITextField 是向下多层的子视图(甚至
一个 UITableViewCell 或 UICollectionViewCell)。
- 此解决方案确实考虑了对键盘视图所做的任何修改。例如:如果您在键盘顶部添加一个 "done" 按钮,这将被计算。
- 滚动调整是动画的。
- 此解决方案在不同方向上都有效。
寻找一种解决方案,阻止 UITextField 在打开时被键盘隐藏,而不管 UITextField 在视图层次结构中的哪个位置,也不管其他 UI 元素。
在线有很多解决方案可以调整您的视图,这样 UITextField 在出现时就不会隐藏在键盘后面,但是,我找不到 "one size fits all" 种解决方案,因此不得不采用很多答案,然后自己做。这是我想出的解决方案。希望它对某人有所帮助:)
首先,此解决方案假定您的 "primary parent" 或 "top level" 视图是 UIScrollView 或后代(例如 UITableView 或 UICollectionView)。如果您的层次结构中没有 UIScrollView,这将不起作用,因为这是用于将 UITextField 滚动到位的。其他解决方案向您展示了如何滚动任何 UIView,但是当您考虑它时,如果您需要将 UITextField 滚动到位,您的视图可能无论如何都应该是可滚动的以阻止它离开屏幕。
在下面创建扩展方法。这将搜索与给定查询匹配的子视图(等)的子视图,并将它们 returns 作为数组。我们稍后会用到它。
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(或您注册事件处理程序的任何地方)中添加这两行。这些注册观察者并保留一个对象引用,以便我们稍后可以取消注册。
_keyboardWillShowObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillShowNotification, Keyboard_Appear);
_keyboardWillHideObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillHideNotification, Keyboard_Disappear);
在 ViewWillDisappear(或您注销事件处理程序的任何地方)中添加这两行。这些从 UIViewController 取消注册观察者,因此他们不再响应事件。
NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardWillShowObserver);
NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardWillHideObserver);
澄清一些事情:
- 当您的 UITextField 是向下多层的子视图(甚至 一个 UITableViewCell 或 UICollectionViewCell)。
- 此解决方案确实考虑了对键盘视图所做的任何修改。例如:如果您在键盘顶部添加一个 "done" 按钮,这将被计算。
- 滚动调整是动画的。
- 此解决方案在不同方向上都有效。