Move focus on next control in Xamarin.Forms

Spending some time with good friends is always a great way to start ideas. So, while talking with one of them, he asked me the best way to handle focus on entries in a Xamarin.Forms Page. I’ve handled the problem many times in iOS and Android native projects, so I decided to create a new control in my library on github.

Welcome TLEntry: the custom Entry control

First of all, we have to create a custom control because the user needs to set the type of return button on the keyboard:

public class TLEntry : Xamarin.Forms.Entry
{
	public static readonly BindableProperty ReturnButtonProperty = 
		BindableProperty.Create("ReturnButton", typeof(ReturnButtonType), typeof(TLEntry), ReturnButtonType.None);

	public ReturnButtonType ReturnButton
	{
		get { return (ReturnButtonType)GetValue(ReturnButtonProperty); }
		set { SetValue(ReturnButtonProperty, value); }
	}
}

After doing that, we need to handle the tap on the button and move the focus on the next control. One way to do that is by knowing the next control and set the focus to it after the next button was pressed. So now we need to know the next control by settings a specific property:

[assembly:ExportRenderer(typeof(TLEntry), typeof(TLEntryRenderer))]
...
public class TLEntry
{
	public static readonly BindableProperty NextViewProperty = 
		BindableProperty.Create("NextView", typeof(View), typeof(TLEntry));

	public View NextView
	{
		get { return (View)GetValue(NextViewProperty); }
		set { SetValue(NextViewProperty, value); }
	}

	public void OnNext()
	{
		NextView?.Focus();
	}
}

Now is the time to create the platform specific renderers.

TLEntryRenderer: the iOS platform-specific renderer

A renderer is a special class with the role of transform a Xamarin Forms control in a native control. So now we needs to transform the TLEntry in a UITextField for the iOS platform. Since we already have renderers for standard control, handle the new ReturnButton and NextView properties simply means to extend the base renderer and create a new one like this:

public class TLEntryRenderer : EntryRenderer
{
	protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
	{
		base.OnElementChanged(e);

		var element = e.NewElement as TLEntry;
		if (element.ReturnButton == ReturnButtonType.Next)
		{
			Control.ReturnKeyType = UIKit.UIReturnKeyType.Next;
			Control.ShouldReturn += (textField) =>
			{
				element.OnNext();
				return false;
			};
		}
	}
}

With this code, we set the ReturnKeyType on UITextView and add an handler that capture the pressure on the return button and go to the next item.

Now, in your Page, you can do something similar:

public partial class FormSamplesPage : ContentPage
{
	TLEntry Entry1 = new TLEntry();
	TLEntry Entry2 = new TLEntry();
	TLEntry Entry3 = new TLEntry();

	protected override void OnAppearing()
	{
		base.OnAppearing();

		Entry1.NextView = Entry2;
		Entry1.ReturnButton = ReturnButtonType.Next;

		Entry2.NextView = Entry3;
		Entry2.ReturnButton = ReturnButtonType.Next;

		Entry3.NextView = Entry1;
		Entry3.ReturnButton = ReturnButtonType.Next;

		this.Body.Children.Add(Entry1);
		this.Body.Children.Add(Entry2);
		this.Body.Children.Add(Entry3);
	}
}

this is the final result:

ezgif-2133599902

Nice!

You can find all code on my github space: https://github.com/fabiocozzolino/TitiusLabs.Xamarin

The Android version will be available soon!

Found a problem? Edit this post