Adding custom buttons to iOS Keyboard in C# & Xamarin


What if you needed some extra keys for text input in your iOS app? Say for e.g.  if you needed text based emoticons on top of the standard keyboard for a chat application. Thankfully UIKit allows apps to have an accessory view above the system keyboard. The area above the keyboard is an extra UIView known as Input Accessory View which you can customize to add your extra keyboard buttons. To add an accessory view, all you gotta do is, set the InputAccessoryView property of the UITextView or UITextField  to an appropriate custom view.

Here’s how the extra keys on top of your standard keyboard looks like:

iOS-Custom-Buttons-C#-Xamarin

Following code sets the text based emoticons to the InputAccessoryView:

		public override void ViewDidLoad ()
		{
			base.ViewDidLoad ();

			UIToolbar toolbar = new UIToolbar (new RectangleF(0.0f, 0.0f, this.View.Frame.Size.Width, 44.0f));

			toolbar.TintColor = UIColor.White;
			toolbar.BarStyle = UIBarStyle.Black;

			toolbar.Translucent = true;

			var myButton = new UIBarButtonItem (":-)",
				UIBarButtonItemStyle.Bordered, AddBarButtonText);

			toolbar.Items = new UIBarButtonItem[]{
				myButton,
				new UIBarButtonItem(":-)",
					UIBarButtonItemStyle.Plain, AddBarButtonText),
				new UIBarButtonItem(":-(",
					UIBarButtonItemStyle.Plain, AddBarButtonText),
				new UIBarButtonItem(";-)",
					UIBarButtonItemStyle.Plain, AddBarButtonText),
				new UIBarButtonItem(":-P",
					UIBarButtonItemStyle.Plain, AddBarButtonText),
				new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace),
				new UIBarButtonItem(UIBarButtonSystemItem.Done, delegate {
					this.SampleText.ResignFirstResponder();
			})
			 };

			this.SampleText.KeyboardAppearance = UIKeyboardAppearance.Dark;
			this.SampleText.InputAccessoryView = toolbar;
		}

		public void AddBarButtonText(object sender, EventArgs e)
		{
			var barButtonItem = sender as UIBarButtonItem;
			if (barButtonItem != null)
				this.SampleText.Text += barButtonItem.Title;

		}

In the above code, we create a UIToolBar with UIBarButtonItems of text based emoticons and set it to the InputAccesoryView property of the SampleText. AddBarButtonText method then handles the key input events.

Playing Input Clicks

You can play standard system keyboard clicks when a user taps in your keyboard accessory views. If you had gone through the apple documentation on Custom Views for Data Input referred earlier, then you would have noticed Objective-C code to do so. Here’s how we can do it elegantly in C#:

  • Create a custom class called MyUIToolBar that inherits from UIToolbar (since we’re using UIToolbar as the custom view for InputAccessoryView)
  • Override the property  EnableInputClicksWhenVisible and return true from it
	public class MyUIToolbar : UIToolbar
	{
		public MyUIToolbar (RectangleF rect) : base(rect)
		{

		}

		public override bool EnableInputClicksWhenVisible {
			get {
				return true;
			}
		}
	}

In the calling code, use the newly created MyUIToolbar

  MyUIToolbar toolbar = new MyUIToolbar (
new RectangleF(0.0f, 0.0f, this.View.Frame.Size.Width, 44.0f));

and make sure you play the sound when user clicks:

public void AddBarButtonText(object sender, EventArgs e)
{
  var barButtonItem = sender as UIBarButtonItem;
  if (barButtonItem != null) {
  this.SampleText.Text += barButtonItem.Title;
  UIDevice.CurrentDevice.PlayInputClick ();
  }
}

Replace the entire keyboard (custom keyboard)?

At times you just want the textbox to input only the keys that you had set. It’s possible to replace the entire keyboard to a custom one. In this case, I just set our emoticon toolbar to InputView property instead of the InputAccessoryView . And this is what it outputs:

iOS-Custom-Keyboard-C#-Xamarin

Source Code

You can download the complete source code from my github repo.

Happy C# Coding!!

-Nish

 

Advertisements

4 thoughts on “Adding custom buttons to iOS Keyboard in C# & Xamarin

  1. Pingback: TechNet Blogs
  2. There is no method to override EnableInputClicksWhenVisible(). gives error – no suitable method found to override.

  3. Is there a way to have multiple rows of buttons? This works great but if I add too many buttons it does not wrap but shrinks the buttons.

  4. I am using the sample ‘Replace the entire keyboard (custom keyboard)?’ on my credit card entry screen which is a popup. When the user clicks on the credit card number UITextView, I display the custom toolbar. If the user locks the iPad when he is on this screen, I get the error shown below and the popup screen closes. Any help on this is greatly appreciated.

    Message “Objective-C exception thrown. Name: NSInvalidArgumentException Reason: *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil\nNative stack trace:\n\t0 CoreFoundation
    0x225d4873 + 150\n\t1 libobjc.A.dylib 0x33feadff objc_exception_throw + 38\n\t2 CoreFoundation 0x224edc1d + 632\n\t3 UIKit
    0x267a84d3 + 510\n\t4 UIKit 0x26f88fe9 + 460\n\t5 UIKit
    0x26f8a025 + 32\n\t6 UIKit 0x26f8325f + 490\n\t7 UIKit
    0x26f8a19d + 48\n\t8 UIKit 0x26f89fff + 98\n\t9 UIKit
    0x26f7f695 + 36\n\t10 UIKit 0x26f89d79 + 1024\n\t11 UIKit
    0x26f82e47 + 38\n\t12 UIKit 0x267d252f + 1146\n\t13 UIKit
    0x26dc7365 + 100\n\t14 UIKit 0x26bdcc33 + 154\n\t15 UIKit
    0x269b05d3 + 822\n\t16 UIKit 0x269b0e39 + 528\n\t17 UIKit
    0x269b0bd7 + 122\n\t18 UIKit 0x269b701b + 158\n\t19 UIKit
    0x269b015d + 268\n\t20 UIKit 0x269bbaf3 + 90\n\t21 UIKit
    0x266fbbc1 + 84\n\t22 CoreFoundation 0x22597091 + 20\n\t23 CoreFoundation
    0x22595387 + 282\n\t24 CoreFoundation 0x225957c5 + 972\n\t25 CoreFoundation 0x224e80d9 CFRunLoopRunSpecific + 516\n\t26 CoreFoundation 0x224e7ecd CFRunLoopRunInMode + 108\n\t27 GraphicsServices 0x2b68faf9 GSEventRunModal + 160\n\t28 UIKit 0x267712dd

    UIApplicationMain + 144\n\t29 eGate 0x002b8214 wrapper_managed_to_native_MonoTouch_UIKit_UIApplication_UIApplicationMain_int_string___intptr_intptr + 272\n\t30 eGate 0x00251f88 MonoTouch_UIKit_UIApplication_Main_string___intptr_intptr + 52\n\t31 eGate 0x00251f48 MonoTouch_UIKit_UIApplication_Main_string___string_string + 204\n\t32 eGate 0x000c5b14 eGate_UI_Touch_Application_Main_string__ + 320\n\t33 eGate 0x004df198 wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 256\n\t34 eGate 0x0113d557 mono_jit_runtime_invoke + 1150\n\t35 eGate 0x0118ddb5 mono_runtime_invoke + 88\n\t36 eGate 0x01191477 mono_runtime_exec_main + 282\n\t37 eGate 0x011f656c xamarin_main + 2072\n\t38 eGate 0x0110b2f1 main + 112\n\t39 libdyld.dylib 0x34738873 + 2\n” string

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s