我有一个视图,其中包含一个
UIScrollview
,滚动视图中包含各种 UITextField
。当我点击 UITextField
输入数据时,UITextField
会向上滚动到 UIScrolView
上方的子视图下,并且从视图中隐藏。我正在使用我在 StackOverflow
上找到的 kewboard 通知解决方案,但当存在滚动视图时它不起作用。我需要做什么才能强制整个视图向上以便文本输入可见?
我的代码:
public override void ViewDidLoad()
{
this.NavigationItem.SetHidesBackButton(true, false);
btnExit.Hidden = false;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var NavBarHeight = UIApplication.SharedApplication.StatusBarFrame.Size.Height +
(NavigationController?.NavigationBar.Frame.Height ?? 0.0);
RegisterForKeyboardNotifications();
scrollView = new UIScrollView
{
Frame = new CGRect(0, 0, View.Frame.Width, h + 2 * padding),
ContentSize = new SizeF((w + padding) * 7, (h + padding) * n),
BackgroundColor = UIColor.White,
AutoresizingMask = UIViewAutoresizing.FlexibleWidth
};
.
.
.
. Bunch of irrelevant code creating subviews to add to scrollview
.
.
.
scrollView.Add(lblDOB);
scrollView.Add(txtDOB);
scrollView.Add(lblFirstName);
scrollView.Add(txtFirstName);
scrollView.Add(lblMI);
scrollView.Add(txtMI);
scrollView.Add(lblLastName);
scrollView.Add(txtLastName);
scrollView.Add(lblSuffix);
scrollView.Add(txtSuffix);
scrollView.Add(lblAddress);
scrollView.Add(txtAddress);
scrollView.Add(lblCity);
scrollView.Add(txtCity);
scrollView.Add(lblState);
scrollView.Add(txtState);
scrollView.Add(lblZip);
scrollView.Add(txtZip);
View.Add(scrollView);
scrollView.BackgroundColor = UIKit.UIColor.White;
scrollView.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
scrollView.AddConstraints(
lblDOB.AtTopOf(scrollView, 0),
lblDOB.AtLeftOf(scrollView, 0),
txtDOB.ToRightOf(lblDOB, 2),
txtDOB.Width().EqualTo(250.0f),
lblFirstName.Below(lblDOB, 5),
txtFirstName.Below(lblDOB, 0).Plus(5),
txtFirstName.ToRightOf(lblFirstName, 2),
txtFirstName.Width().EqualTo(250.0f),
lblMI.Below(lblFirstName, 5),
txtMI.Below(lblFirstName, 0).Plus(5),
txtMI.ToRightOf(lblMI, 2),
txtMI.Width().EqualTo(50.0f),
lblLastName.Below(lblMI, 5),
txtLastName.Below(lblMI, 0).Plus(5),
txtLastName.ToRightOf(lblLastName, 2),
txtLastName.Width().EqualTo(250.0f),
lblSuffix.Below(lblLastName, 5),
txtSuffix.Below(lblLastName, 0).Plus(5),
txtSuffix.ToRightOf(lblSuffix, 2),
txtSuffix.Width().EqualTo(50.0f),
lblAddress.Below(lblSuffix, 5),
txtAddress.Below(lblSuffix, 0).Plus(5),
txtAddress.ToRightOf(lblAddress, 2),
txtAddress.Width().EqualTo(250.0f),
lblCity.Below(lblAddress, 5),
txtCity.Below(lblAddress, 0).Plus(5),
txtCity.ToRightOf(lblCity, 2),
txtCity.Width().EqualTo(250.0f),
lblState.Below(lblCity, 5),
txtState.Below(lblCity, 0).Plus(5),
txtState.ToRightOf(lblState, 2),
txtState.Width().EqualTo(250.0f),
lblZip.Below(lblState, 5),
txtZip.Below(lblState, 0).Plus(5),
txtZip.ToRightOf(lblZip, 2),
txtZip.Width().EqualTo(250.0f)
);
View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
View.AddConstraints
(
banner.AtTopOf(View, (float)NavBarHeight),
banner.AtRightOf(View, 0),
banner.AtLeftOf(View, 0),
employeeimage.Below(banner, 2),
employeeimage.Height().EqualTo(180),
employeeimage.Width().EqualTo(180),
btnSave.AtTopOf(employeeimage),
btnSave.ToRightOf(employeeimage, 5),
btnExit.Below(btnSave),
btnExit.WithSameLeft(btnSave),
btnExit.WithSameWidth(btnSave),
lblName.Below(employeeimage, 2),
lblName.WithSameWidth(banner),
line.Below(lblName, 0),
line.WithSameWidth(banner),
line.Height().EqualTo(2),
scrollView.Below(line, 0),
scrollView.AtBottomOf(View, 10),
scrollView.AtLeftOf(View, 10),
scrollView.AtRightOf(View, 10)
);
视图正确显示,所有子视图都存在。当键盘弹出时应该将视图向上推的代码是:
protected virtual void RegisterForKeyboardNotifications()
{
_keyboardObserverWillShow = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillShowNotification, KeyboardWillShowNotification);
_keyboardObserverWillHide = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillHideNotification, KeyboardWillHideNotification);
}
protected virtual void UnregisterKeyboardNotifications()
{
NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardObserverWillShow);
NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardObserverWillHide);
}
protected virtual UIView KeyboardGetActiveView()
{
return this.View.FindFirstResponder();
}
protected virtual void KeyboardWillShowNotification(NSNotification notification)
{
UIView activeView = KeyboardGetActiveView();
if (activeView == null)
return;
UIScrollView scrollView = activeView.FindSuperviewOfType(this.View, typeof(UIScrollView)) as UIScrollView;
if (scrollView == null)
return;
RectangleF keyboardBounds = (RectangleF)UIKeyboard.BoundsFromNotification(notification);
UIEdgeInsets contentInsets = new UIEdgeInsets(0.0f, 0.0f, keyboardBounds.Size.Height, 0.0f);
scrollView.ContentInset = contentInsets;
scrollView.ScrollIndicatorInsets = contentInsets;
// If activeField is hidden by keyboard, scroll it so it's visible
RectangleF viewRectAboveKeyboard = new RectangleF((PointF)this.View.Frame.Location, new SizeF((float)this.View.Frame.Width, (float)(this.View.Frame.Size.Height - keyboardBounds.Size.Height)));
RectangleF activeFieldAbsoluteFrame = (RectangleF)activeView.Superview.ConvertRectToView(activeView.Frame, this.View);
// activeFieldAbsoluteFrame is relative to this.View so does not include any scrollView.ContentOffset
// Check if the activeField will be partially or entirely covered by the keyboard
if (!viewRectAboveKeyboard.Contains(activeFieldAbsoluteFrame))
{
// Scroll to the activeField Y position + activeField.Height + current scrollView.ContentOffset.Y - the keyboard Height
PointF scrollPoint = new PointF(0.0f, (float)(activeFieldAbsoluteFrame.Location.Y + activeFieldAbsoluteFrame.Height + scrollView.ContentOffset.Y - viewRectAboveKeyboard.Height));
scrollView.SetContentOffset(scrollPoint, true);
}
}
protected virtual void KeyboardWillHideNotification(NSNotification notification)
{
UIView activeView = KeyboardGetActiveView();
if (activeView == null)
return;
UIScrollView scrollView = activeView.FindSuperviewOfType(this.View, typeof(UIScrollView)) as UIScrollView;
if (scrollView == null)
return;
// Reset the content inset of the scrollView and animate using the current keyboard animation duration
double animationDuration = UIKeyboard.AnimationDurationFromNotification(notification);
UIEdgeInsets contentInsets = new UIEdgeInsets(0.0f, 0.0f, 0.0f, 0.0f);
UIView.Animate(animationDuration, delegate {
scrollView.ContentInset = contentInsets;
scrollView.ScrollIndicatorInsets = contentInsets;
});
}
查看扩展类:
public static class ViewExtensions
{
public static UIView FindFirstResponder(this UIView view)
{
if (view.IsFirstResponder)
{
return view;
}
foreach (UIView subView in view.Subviews)
{
var firstResponder = subView.FindFirstResponder();
if (firstResponder != null)
return firstResponder;
}
return null;
}
public static UIView FindSuperviewOfType(this UIView view, UIView stopAt, Type type)
{
if (view.Superview != null)
{
if (type.IsAssignableFrom(view.Superview.GetType()))
{
return view.Superview;
}
if (view.Superview != stopAt)
return view.Superview.FindSuperviewOfType(stopAt, type);
}
return null;
}
}
当点击DOB文本视图时,文本视图消失在位于滚动视图上方的子视图下,我已经尝试了我能想到的一切以及我在网上找到的各种方法,但似乎没有任何效果。有什么建议吗?
好吧,我无法使问题中的代码像我需要的那样工作,但我确实发现了这个:
这几乎是完美的,我从 NuGet 安装了
IQKeyboardManager
并将以下代码添加到我的应用程序的初始视图控制器中:
Xamarin.IQKeyboardManager.SharedManager.EnableAutoToolbar = true;
Xamarin.IQKeyboardManager.SharedManager.ShouldResignOnTouchOutside = true;
Xamarin.IQKeyboardManager.SharedManager.ShouldToolbarUsesTextFieldTintColor = true;
Xamarin.IQKeyboardManager.SharedManager.KeyboardDistanceFromTextField = 150f;
我只需要弄清楚如何阻止滚动视图向上推,但我可以接受默认设置,因为用户可以将文本字段滚动回视图中,但我认为我可以让它停止这样做。否则,这非常有效。