Custom Keyboard in Xamarin forms

后端 未结 1 1097
悲哀的现实
悲哀的现实 2020-12-15 23:57

I\'ve read the many posts on the forum and on StackOverflow and other places on making custom keyboards, but have not found an approach that will work for my Xamarin forms c

相关标签:
1条回答
  • Custom Keyboard in Xamarin forms

    You could create a PageRenderer and use native .axml layout file to create the custom Keyboard.

    For example, my KeyboardPageRenderer :

    [assembly: ExportRenderer(typeof(MyKeyboardPage), typeof(KeyboardPageRenderer))]
    ...
    public class KeyboardPageRenderer : PageRenderer
    {
    
        public CustomKeyboardView mKeyboardView;
        public EditText mTargetView;
        public Android.InputMethodServices.Keyboard mKeyboard;
        Activity activity;
        global::Android.Views.View view;
    
        protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
        {
            base.OnElementChanged(e);
    
            if (e.OldElement != null || Element == null)
            {
                return;
            }
    
            try
            {
                SetupUserInterface();
                SetupEventHandlers();
                this.AddView(view);
            }
            catch (System.Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(@"           ERROR: ", ex.Message);
            }
        }
    
        void SetupUserInterface()
        {
            activity = this.Context as Activity;
            view = activity.LayoutInflater.Inflate(Resource.Layout.activity_keyboard, this, false);
    
            mKeyboard = new Android.InputMethodServices.Keyboard(Context, Resource.Xml.keyboard);
            mTargetView = view.FindViewById<EditText>(Resource.Id.target);
    
            mKeyboardView = view.FindViewById<CustomKeyboardView>(Resource.Id.keyboard_view);
            mKeyboardView.Keyboard = mKeyboard;
        }
    
        void SetupEventHandlers()
        {
            mTargetView.Touch += (sender, e) =>
            {
                ShowKeyboardWithAnimation();
                e.Handled = false;
                mTargetView.ShowSoftInputOnFocus = false;
            };
    
            mKeyboardView.Key += async (sender, e) =>
            {
                long eventTime = JavaSystem.CurrentTimeMillis();
                KeyEvent ev = new KeyEvent(eventTime, eventTime, KeyEventActions.Down, e.PrimaryCode, 0, 0, 0, 0, KeyEventFlags.SoftKeyboard | KeyEventFlags.KeepTouchMode);
    
                DispatchKeyEvent(ev);
    
                await Task.Delay(1);
    
                mTargetView.RequestFocus();
            };
        }
    
    
        public void ShowKeyboardWithAnimation()
        {
            if (mKeyboardView.Visibility == ViewStates.Gone)
            {
                mKeyboardView.Visibility = ViewStates.Visible;
                Android.Views.Animations.Animation animation = AnimationUtils.LoadAnimation(
                    Context,
                    Resource.Animation.slide_in_bottom
                );
                mKeyboardView.ShowWithAnimation(animation);
            }
        }
    
        protected override void OnLayout(bool changed, int l, int t, int r, int b)
        {
            base.OnLayout(changed, l, t, r, b);
    
            var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly);
            var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly);
    
            view.Measure(msw, msh);
            view.Layout(0, 0, r - l, b - t);
        }
    }
    

    Effect:

    Sample implementation[Effect].

    I wrote up a simple demo about how to implement this feature, you can see it in this GitHub Repository.

    I don't know Hebrew, if you need to achieve the effect like the picture you have post, you need custom the layout in keyboard.xml file.

    Update :

    I am done iOS portion using entry render so only try to do for android portion

    I write a EntryRenderer to implement this feature, effect like this, hope this can help you.

    public class MyEntry2Renderer :  ViewRenderer<MyEntry, TextInputLayout>,
        ITextWatcher,
        TextView.IOnEditorActionListener
    {
        private bool _hasFocus;
    
        public CustomKeyboardView mKeyboardView;
        public Android.InputMethodServices.Keyboard mKeyboard;
    
        ViewGroup activityRootView;
    
        protected EditText EditText => Control.EditText;
    
        public bool OnEditorAction(TextView v, ImeAction actionId, KeyEvent e)
        {
            if ((actionId == ImeAction.Done) || ((actionId == ImeAction.ImeNull) && (e.KeyCode == Keycode.Enter)))
            {
                Control.ClearFocus();
                //HideKeyboard();
                ((IEntryController)Element).SendCompleted();
            }
            return true;
        }
    
        public virtual void AfterTextChanged(IEditable s)
        {
        }
    
        public virtual void BeforeTextChanged(ICharSequence s, int start, int count, int after)
        {
        }
    
        public virtual void OnTextChanged(ICharSequence s, int start, int before, int count)
        {
            if (string.IsNullOrWhiteSpace(Element.Text) && (s.Length() == 0)) return;
            ((IElementController)Element).SetValueFromRenderer(Entry.TextProperty, s.ToString());
        }
    
        protected override TextInputLayout CreateNativeControl()
        {
            var textInputLayout = new TextInputLayout(Context);
            var editText = new EditText(Context);
    
            #region Add the custom Keyboard in your Page
            var activity = Forms.Context as Activity;
            var rootView = activity.Window.DecorView.FindViewById(Android.Resource.Id.Content);
    
            activity.Window.SetSoftInputMode(SoftInput.StateAlwaysHidden);
    
            activityRootView = ((ViewGroup)rootView).GetChildAt(0) as ViewGroup;
            mKeyboardView = new CustomKeyboardView(Forms.Context, null);
    
            Android.Widget.RelativeLayout.LayoutParams layoutParams =
                new Android.Widget.RelativeLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.WrapContent); // or wrap_content
            layoutParams.AddRule(LayoutRules.AlignParentBottom);
            activityRootView.AddView(mKeyboardView, layoutParams);
            #endregion
    
            //First open the current page, hide the Keyboard
            mKeyboardView.Visibility = ViewStates.Gone;
    
            //Use the custom Keyboard
            mKeyboard = new Android.InputMethodServices.Keyboard(Context, Resource.Xml.keyboard2);
            mKeyboardView.Keyboard = mKeyboard;
    
            mKeyboardView.Key += async (sender, e) =>
            {
                long eventTime = JavaSystem.CurrentTimeMillis();
                KeyEvent ev = new KeyEvent(eventTime, eventTime, KeyEventActions.Down, e.PrimaryCode, 0, 0, 0, 0, KeyEventFlags.SoftKeyboard | KeyEventFlags.KeepTouchMode);
    
                DispatchKeyEvent(ev);
    
                await Task.Delay(1);
            };
    
            textInputLayout.AddView(editText);
            return textInputLayout;
        }
    
    
        protected override void OnElementChanged(ElementChangedEventArgs<MyEntry> e)
        {
            base.OnElementChanged(e);
    
            if (e.OldElement != null)
                if (Control != null)
                    EditText.FocusChange -= ControlOnFocusChange;
    
            if (e.NewElement != null)
            {
                var ctrl = CreateNativeControl();
                SetNativeControl(ctrl);
    
                EditText.ShowSoftInputOnFocus = false;
    
                EditText.FocusChange += ControlOnFocusChange;
            }
        }
    
        private void ControlOnFocusChange(object sender, FocusChangeEventArgs args)
        {
            _hasFocus = args.HasFocus;
            if (_hasFocus)
            {
                EditText.Post(() =>
                {
                    EditText.RequestFocus();
                    ShowKeyboardWithAnimation();
                });
            }
            else
            {
                //Hide the Keyboard
                mKeyboardView.Visibility = ViewStates.Gone;
            }
        }
    
        public void ShowKeyboardWithAnimation()
        {
            if (mKeyboardView.Visibility == ViewStates.Gone)
            {
                mKeyboardView.Visibility = ViewStates.Visible;
                Android.Views.Animations.Animation animation = AnimationUtils.LoadAnimation(
                    Context,
                    Resource.Animation.slide_in_bottom
                );
                mKeyboardView.ShowWithAnimation(animation);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题