MonoTouch: UITextField с InputView DatePicker, скрытым клавиатурой в альбомной ориентации

У меня есть UITextField, который я размещаю внизу экрана:

UITextField Нижняя часть экрана

Обычно это текстовое поле будет скрыто клавиатурой, но я использовал комбинацию:

И создал мой UITextField, который при выборе будет отображать средство выбора даты, а UITextField автоматически прокручивается вверх:

UITextField с DatePicker

Это прекрасно работает, пока я не поверну телефон в альбомную ориентацию.

Однажды в альбомной ориентации мой UITextField выдвигается слишком далеко вверх по экрану, где его больше не видно.

Пейзаж UITextField DatePicker

В коде я подписываюсь на UIKeyboard.WillShowNotification и вызываю KeyboardWillShowNotification ниже:

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 = UIKeyboard.FrameBeginFromNotification(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(this.View.Frame.Location, new SizeF(this.View.Frame.Width, this.View.Frame.Size.Height - keyboardBounds.Size.Height));

            RectangleF activeFieldAbsoluteFrame = 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, activeFieldAbsoluteFrame.Location.Y + activeFieldAbsoluteFrame.Height + scrollView.ContentOffset.Y - viewRectAboveKeyboard.Height);
                scrollView.SetContentOffset(scrollPoint, true);
            }
        }

Две дополнительные функции:

protected virtual UIView KeyboardGetActiveView()
        {
            return this.View.FindFirstResponder();
        }

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;
    }

Полный исходный код доступен на BitBucket: https://bitbucket.org/benhysell/uitextfielddatepicker

Идеи о том, что я могу делать неправильно?


person ben    schedule 27.10.2012    source источник


Ответы (1)


Когда отображается клавиатура, вы должны изменить высоту вашего представления.

Что-то вроде этого:

var frame = View.Frame;
frame.Height -= keyboardHeight;
View.Frame = frame;

Чтобы получить высоту клавиатуры:

bool isLandscape = InterfaceOrientation == UIInterfaceOrientation.LandscapeLeft || InterfaceOrientation == UIInterfaceOrientation.LandscapeRight;
var keyboardFrame = UIKeyboard.FrameEndFromNotification (notification);
var keyboardHeight = isLandscape ? keyboardFrame.Width : keyboardFrame.Height;

Пока AutoResizingMask вашего UITextField настроено так, что оно будет центрироваться, ваш пользовательский интерфейс должен выглядеть правильно.

person jonathanpeppers    schedule 30.10.2012