【发布时间】:2020-05-26 21:09:03
【问题描述】:
寻找一种解决方案,以阻止 UITextField 在打开时被键盘隐藏,而不管 UITextField 在视图层次结构中的位置以及其他 UI 元素。
【问题讨论】:
标签: ios xamarin keyboard uitextfield
寻找一种解决方案,以阻止 UITextField 在打开时被键盘隐藏,而不管 UITextField 在视图层次结构中的位置以及其他 UI 元素。
【问题讨论】:
标签: ios xamarin keyboard uitextfield
网上有很多解决方案可以调整您的视图,以便 UITextField 在出现时不会隐藏在键盘后面,但是我找不到“一刀切”的解决方案,因此不得不进行大量调整的答案,让我自己的。这是我想出的解决方案。希望它可以帮助某人:)
首先,此解决方案假定您的“主要父级”或“顶级”视图是 UIScrollView 或后代(例如 UITableView 或 UICollectionView)。如果您的层次结构中没有 UIScrollView,这将不起作用,因为这是用于将 UITextField 滚动到位的内容。其他解决方案向您展示了如何滚动任何 UIView,但是当您考虑它时,如果您需要将 UITextField 滚动到位,那么您的视图应该可以滚动以阻止它离开屏幕。
在下面创建扩展方法。这将搜索与给定查询匹配的子视图(等)的子视图,并将它们作为数组返回。我们稍后会用到它。
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);
澄清几点:
【讨论】: