Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keyboard quickly hides and reappears on Android using Xamarin Forms

We're trying to build a Chat App using Xamarin Forms, but we keep getting this annoying bug with the Android keyboard. Whenever the "Send" button is tapped, the focus on the Entry (text box for chatting) is lost and the keyboard disappears. That isn't what we wanted so we added this line to the TapGestureRecognizer:

messageEntry.Focus();

But for some reason, this doesn't happen fast enough, and often the keyboard goes down and immediately up again. This prevents users from quickly posting multiple message sequentially. Does anybody know how this can be fixed?

like image 894
gerwin Avatar asked Jan 16 '15 22:01

gerwin


1 Answers

Thanks to the answer of @AdamKemp in this post, here is my solution. If the touch is within my EntryStackLayout (don't forget to create the empty custom renderer), then I don't dismiss the keyboard (which is what DispatchTouchEvent will do if CurrentFocus is EditText).

public class EditorAndButtonReproPage : ContentPage
    {
        public EditorAndButtonReproPage()
        {
            BackgroundColor = Color.Gray;
            Padding = 50;
            var editor = new Editor {HorizontalOptions = LayoutOptions.FillAndExpand};
            var editorButton = new Button {Text = "OK", HorizontalOptions = LayoutOptions.End};
            var editorLayout = new EntryStackLayout { Orientation = StackOrientation.Horizontal, Children = { editor, editorButton}, VerticalOptions = LayoutOptions.Start};
            var entry = new ExtendedEntry { Placeholder = "Entry", HorizontalOptions = LayoutOptions.FillAndExpand };
            var entryButton = new Button { Text = "OK", HorizontalOptions = LayoutOptions.End };
            var entryLayout = new EntryStackLayout { Orientation = StackOrientation.Horizontal, Children = { entry, entryButton }, VerticalOptions = LayoutOptions.Start };
            Content = new StackLayout {Children = {editorLayout, entryLayout}};
        }
    }

and in the MainActivity:

private bool _ignoreNewFocus;
        public override bool DispatchTouchEvent(MotionEvent e)
        {
            var currentView = CurrentFocus;
            var parent = currentView?.Parent?.Parent;
            var entryStackLayout = parent as EntryStackLayout;
            if (entryStackLayout != null)
            {
                var entryLayoutLocation = new int[2];
                entryStackLayout.GetLocationOnScreen(entryLayoutLocation);
                var x = e.RawX + entryStackLayout.Left - entryLayoutLocation[0];
                var y = e.RawY + entryStackLayout.Top - entryLayoutLocation[1];
                var entryStackLayoutRect = new Rectangle(entryStackLayout.Left, entryStackLayout.Top, entryStackLayout.Width, entryStackLayout.Height);
                _ignoreNewFocus = entryStackLayoutRect.Contains(x, y);
            }
            var result = base.DispatchTouchEvent(e);
            _ignoreNewFocus = false;
            return result;
        }

        public override Android.Views.View CurrentFocus => _ignoreNewFocus ? null : base.CurrentFocus;
like image 105
François Avatar answered Oct 15 '22 03:10

François