question

platinum78-8626 avatar image
0 Votes"
platinum78-8626 asked platinum78-8626 commented

Creating a Custom Keyboard in Xamarin.Forms : Weird Focus Event Behavior

I'm working on a personal project to study Xamarin.Forms, and I'm stuck in creating a custom keyboard.
What I want to do is to type characters into <Entry> when some some buttons in the page are clicked, while constantly keeping the focus to the entry.
It's essentially a custom keyboard; the <Entry> does not lose focus, or immediately retakes it.
To implement this, I have set a callback that sets focus to the <Entry> again, and then appends the string allocated to the pressed button to the <Entry>.
The callback function looks like below.

 public void KeyPressCallback(string keyText)
 {
     // Return focus to input area.
     FormulaViewer.SetFocus(); // This function internally does Entry.Focus()

     // This code internally processes text from clicked button, and allocates it to the Entry.
     _formulaParser.ProcessInput(keyText, FormulaViewer.InputPosition);
     FormulaViewer.InputText = _formulaParser.FormulaString;
 }


Alongside, I made a custom renderer of <Entry> that keeps the view from showing soft keyboard at focus, as shown in the below tutorial.
https://theconfuzedsourcecode.wordpress.com/2017/05/19/a-keyboard-disabled-entry-control-in-xamarin-forms/

Now the problem rises.

When I simply tap the entry, only <Focused> event is raised, and the soft keyboard does not show up.
When I press the button, followed by the callback function above, both <Focused> and <FocusChangeRequested> events are raised, and the soft keyboard shows up.

I've been searching a lot to fix this, but I don't see any remedy yet.
Any comment would be greatly helpful.

dotnet-csharpdotnet-xamarinforms
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

JarvanZhang-MSFT avatar image
1 Vote"
JarvanZhang-MSFT answered platinum78-8626 commented

Hello @platinum78-8626 ,​

Welcome to our Microsoft Q&A platform!

I created a basic demo to test the function, and reproduced the issue on my side. The function code of the custom renderer class works fine if we click the 'Entry' directly to make it focus on. The problem will only occur when calling the Focus() method. I check the source code about the method but it doesn't provide the working mechanism. We cannot get how the Focus() method perform in each native platform. If you want to get out this problem, it's suggested to report it to the Xamarin.Forms github repo for help.

To avoid the problem, here is a workaround which uses the native code to set focus for the entry instead. I add a bool parameter to the custom entry class. Obtain the parameter in the render class to check the value to change the focus status.

Here is the related code, you could refer to:

public class CustomEntry : Entry
{
    public static readonly BindableProperty CustomFocusProperty = BindableProperty.Create(nameof(CustomFocus), typeof(bool), typeof(CustomEntry), null);

    public bool CustomFocus
    {
        get => (bool)GetValue(CustomFocusProperty);
        set => SetValue(CustomFocusProperty, value);
    }
}

[assembly:ExportRenderer(typeof(CustomEntry),typeof(CustomEntryRenderer))]
namespace TestApplication_6.Droid
{
    public class CustomEntryRenderer : EntryRenderer
    {
        public CustomEntryRenderer(Context context) : base(context)
        {
        }

        CustomEntry entry;
        EditText editText;
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            entry = Element as CustomEntry;
            editText = Control as EditText;
            editText.FocusChange += EditText_FocusChange;
        }

        private void EditText_FocusChange(object sender, FocusChangeEventArgs e)
        {
            this.Control.ShowSoftInputOnFocus = false;
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (entry.CustomFocus)
            {
                editText.RequestFocus();
            }
            else
            {
                editText.ClearFocus();
            }
        }
    }
}

Change the parameter's value to set focus for the entry:

public partial class TestPage : CustomPage
{
    public TestPage()
    {
        InitializeComponent();
    }
    private async void Button_Clicked(object sender, EventArgs e)
    {
        entry.CustomFocus = false;
        entry.Text += "testing";
        entry.CustomFocus = true;
    }
    private void Entry_Focused(object sender, FocusEventArgs e)
    {
    }
}


Best Regards,

Jarvan Zhang


If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.





· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi, @platinum78-8626
I have not heard from you for a couple of days. Please let me know if there is anything that I can help here.

1 Vote 1 ·

Thanks for the answer. I've been working on another part of the project, so I'll give a try and report if there is any additional issue using this solution.

0 Votes 0 ·