[Xamarin.Forms iOS] How to Override the Text of the SearchBar’s Cancel Button

The iOS SearchBar UI control per default includes a Cancel button that allows the user to clear the text in the search field. The button appears automatically when the user starts to type in the text and disappears when the user deletes the text. The Xamarin implementation of the SearchBar control allows deactivating the button. However, it does not provide any possibility to override the text shown on the button, which is “Cancel”. In this short tutorial, I will show how to override the Cancel Button’s text of the iOS SearchBar in Xamarin Forms.

For this tutorial, I have used the following tools and packages:

  • Visual Studio for Mac Community Edition Version 8.9.1
  • Xamarin.Forms NuGet Package Version 5.0.0.2012

To override the Cancel button’s text, we will need to create a custom renderer for the SearchBar control. For that, in the iOS project of your Xamarin solution, create a new folder and call it Renderers.

Next, create a new class in that folder and name it CustomSearchBarRenderer.

Subsequently, replace the content of that class with the following code (Note: you will need to substitute the namespace OverrideSearchBarCancelButtonText with the namespace of your project):

using OverrideSearchBarCancelButtonText.iOS.Renderers;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(SearchBar), typeof(CustomSearchBarRenderer))]
namespace OverrideSearchBarCancelButtonText.iOS.Renderers
{
    public class CustomSearchBarRenderer : SearchBarRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                Control.TextChanged += Control_TextChanged;
            }
        }

        private void Control_TextChanged(object sender, UISearchBarTextChangedEventArgs e)
        {
            if (Control != null)
            {
                UIButton button = GetCancelButton(Control);
                if (button != null)
                {
                    button.SetTitle("Go!", UIControlState.Normal);
                }
                else
                {
                    Control.ShowsCancelButton = false;
                }
            }
        }

        private UIButton GetCancelButton(UIView view)
        {
            if (view.GetType() == typeof(UIButton))
                return view as UIButton;

            if (view.Subviews == null || view.Subviews.Length == 0)
                return null;

            foreach (UIView v in view.Subviews)
            {
                var result = GetCancelButton(v);
                if (result != null)
                    return result;
            }

            return null;
        }
    }
}

Custom renderers in Xamarin allows us to override UI components on a low-level. In this particular case, we override the SearchBar control and export it as a new SearchBar control (line 6). That means that you will override all Xamarin SearchBar controls in your project. Note: If you do not want to override all controls but only some of them, then you need to implement a new control (e.g., MySearchBar) by deriving from the SearchBar class. In the custom renderer, you will then need to export the renderer for the type MySearchBar as follows: [assembly: ExportRenderer(typeof(MySearchBar), typeof(CustomSearchBarRenderer))].

Since the Cancel button is not always presented in the SearchBar control, but is created and deleted depending on the content of search field content, we have to override the button on each text change. As our CustomSearchBarRenderer derives from the SearchBarRenderer, we can override the OnElementChanged event, which is called directly after the element has been created, and attach our event handler to the TextChanged event. Now, every time the text becomes changed, our event handler will fire.

In the event handler Control_TextChanged, we can look now if the SearchBar control contains the Cancel button. For that, we execute the function GetCancelButton. This function searches recursively for the Cancel button in the visual hierarchy of the SearchBar control using the Depth-first search (DFS) approach. As a result, the function returns a reference to the Cancel button if presented and null if not.

Finally, we can update the Cancel button’s text using the SetTitle method (line 28). In the image below, you can see the result.

You can find the sample code for this tutorial on the GitHub: https://github.com/asigitov/OverrideSearchBarCancelButtonText

Useful Links

%d