kaolick kaolick - 4 months ago 74
Android Question

Changing keyboard's ImeOptions of Xamarin.Forms.Entry in custom renderer not working on Android

What I have:

I have a custom class

MyEntry
derived from
Xamarin.Forms.Entry
and custom renderer classes
MyEntryRenderer
for Android and iOS.

What I want:

I want to change the keyboard's "enter"-button to a "search"-button by changing
ImeOptions
on
Android
and
ReturnKeyType
on
iOS
(see sample code). When I press the altered "search"-button, the
MyEntry.Completed
event should be called (like before when I pressed the un-altered "enter"-button.

What really happens:

On
iOS
the code works like expected. But on
Android
nothing happens. The event doesn't get called.

My question:

How can I achieve what I described above on
Android
?

Sample code:

App.cs:

namespace CustomEntry
{
public class App
{
public static Page GetMainPage()
{
MyEntry entry = new MyEntry {
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
Placeholder = "Enter some text"
};

entry.Completed += delegate {
Console.WriteLine("Completed");
};

return new ContentPage {
Content = entry,
};
}
}
}


MyEntry.cs:

namespace CustomEntry
{
public class MyEntry:Entry
{

}
}


MyEntryRenderer.cs (Android):

[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace CustomEntry.Android
{
public class MyEntryRenderer:EntryRenderer
{

protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);

if (Control != null) {
Control.ImeOptions = global::Android.Views.InputMethods.ImeAction.Search;
}
}

}
}


MyEntryRenderer.cs (iOS):

[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace CustomEntry.iOS
{
public class MyEntryRenderer:EntryRenderer
{

protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);

if (Control != null) {
Control.ReturnKeyType = UIReturnKeyType.Search;
}
}

}
}

Answer

I found a workaround for my problem myself:

First I added an Action to my custom entry to be called when I press my "search"-button.

MyEntry.cs

namespace CustomEntry
{
    public class MyEntry:Entry
    {
        public Action SearchPressed = delegate {
        };
    }
}

Second I "listen" for ImeAction.Search like this and call the Action I added to my custom entry.

MyEntryRenderer.cs (Android):

[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace CustomEntry.Android
{
    public class MyEntryRenderer:EntryRenderer
    {

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            if (Control != null) {
                Control.ImeOptions = ImeAction.Search;
                Control.EditorAction += (sender, args) => {
                    if (args.ActionId == ImeAction.Search) {
                        var entry = (AddressEntry)Element;
                        entry.SearchPressed();
                    }
                };
            }
        }

    }
}

In a third class where I use MyEntry I can run some code when the "search"-button is pressed like this:

var myEntry = new MyEntry();
myEntry.SearchPressed += SomeMethod;