How do I keep my Editor from scrolling below keyboard when moving the cursor?

时间:2018-03-25 19:00:12

标签: xamarin.forms xamarin.android

I've got an Editor which is tall enough to accommodate multiple lines of input. The editor is at the bottom of the screen if it matters. Once multiple lines are entered, if you move the cursor up a line, the entire view shifts downward, so the line you just left is now obscured by the keyboard. I'd like it to not do this unless the line the cursor is on is either off screen or close to being off screen. Sort of like how the built in Android message app works. Here's what I mean in pictures.

enter image description here

  1. Default state, everything looks good. We have 3 lines of input

enter image description here

  1. I move the cursor up one line: notice that the entire view has shifted down one line and so "line 3" is now obscured. I don't want this behavior (it among other things hides some UI elements).

enter image description here

  1. This is the Android messaging app. This is the behavior I want: when you move the cursor to that next line, the view doesn't just shift downward. If you have enough lines to scroll past the visible area, Android just shifts the text and not the entire view to accommodate it.

In essence, I just want the contents of the editor to shift (when appropriate) and not the entire window.

1 个答案:

答案 0 :(得分:0)

我设法搞清楚了。首先,在MainActivity.cs中,在LoadApplication调用之后,我添加了这个:

Xamarin.Forms.Application.Current.On<Xamarin.Forms.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);

使用默认值或.Pan根本不起作用。请注意,这样做并没有解决问题。我还必须学习here所描述的课程并使用它。如果没有这个课程,事情就无法正常运作。此页面上描述的“替代方法”也不起作用(基本上只是改变软输入模式调整)。

如果我提到的链接死了,这就是课程。我稍微对其进行了修改,因此默认情况下未启用。您只需在其上设置Disabled = false即可启用它。您还可以调用静态方法 Init 来初始化类。

public class AndroidBug5497WorkaroundForXamarinAndroid
    {

        private readonly View _childOfContent;
        private readonly FrameLayout.LayoutParams _frameLayoutParams;
        private int _usableHeightPrevious;

        public static AndroidBug5497WorkaroundForXamarinAndroid Instance { get; private set; }

        private bool _disabled = true;
        public bool Disabled
        {
            get => _disabled;
            set
            {
                if (_disabled != value)
                {
                    _disabled = value;
                    if (_disabled)
                        _childOfContent.ViewTreeObserver.GlobalLayout -= PossiblyResizeChildOfContent;
                    else
                        _childOfContent.ViewTreeObserver.GlobalLayout += PossiblyResizeChildOfContent;
                }
            }
        }

        public static void Init(Activity activity)
        {
            if (Instance != null)
                return;

            Instance = new AndroidBug5497WorkaroundForXamarinAndroid(activity);
        }

        private AndroidBug5497WorkaroundForXamarinAndroid(Activity activity)
        {
            FrameLayout content = (FrameLayout)activity.FindViewById(Android.Resource.Id.Content);
            _childOfContent = content.GetChildAt(0);            
            _frameLayoutParams = (FrameLayout.LayoutParams)_childOfContent.LayoutParameters;
        }

        private void PossiblyResizeChildOfContent(object sender, EventArgs e)
        {
            int usableHeightNow = ComputeUsableHeight();
            if (usableHeightNow != _usableHeightPrevious)
            {
                var usableHeightSansKeyboard = _childOfContent.RootView.Height;
                var heightDifference = usableHeightSansKeyboard - usableHeightNow;

                _frameLayoutParams.Height = usableHeightSansKeyboard - heightDifference;

                _childOfContent.RequestLayout();
                _usableHeightPrevious = usableHeightNow;
            }
        }

        private int ComputeUsableHeight()
        {
            Rect r = new Rect();
            _childOfContent.GetWindowVisibleDisplayFrame(r);
            return (r.Bottom - r.Top);
        }