Xamarin.iOS - 需要在文本输入时向上移动整个视图

问题描述 投票:0回答:1

我有一个视图,其中包含一个

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文本视图时,文本视图消失在位于滚动视图上方的子视图下,我已经尝试了我能想到的一切以及我在网上找到的各种方法,但似乎没有任何效果。有什么建议吗?

c# ios xamarin.ios
1个回答
0
投票

好吧,我无法使问题中的代码像我需要的那样工作,但我确实发现了这个:

出现键盘时滚动的 ViewController

这几乎是完美的,我从 NuGet 安装了

IQKeyboardManager
并将以下代码添加到我的应用程序的初始视图控制器中:

    Xamarin.IQKeyboardManager.SharedManager.EnableAutoToolbar = true;
    Xamarin.IQKeyboardManager.SharedManager.ShouldResignOnTouchOutside = true;
    Xamarin.IQKeyboardManager.SharedManager.ShouldToolbarUsesTextFieldTintColor = true;
    Xamarin.IQKeyboardManager.SharedManager.KeyboardDistanceFromTextField = 150f;

我只需要弄清楚如何阻止滚动视图向上推,但我可以接受默认设置,因为用户可以将文本字段滚动回视图中,但我认为我可以让它停止这样做。否则,这非常有效。

© www.soinside.com 2019 - 2024. All rights reserved.