4
votes

We are internationalizing a mobile app my team is developing, and I noticed the "Cancel" button in the SearchBar is not translating (everything else is translating just fine) - it always says "Cancel" in English no matter what language I change the iPad simulator to. If I can set the text myself, then I can ensure it's internationalized properly. So...

How do I change the "Cancel" button text on a Xamarin.Forms SearchBar? I've tried a custom renderer, but am having difficulty targeting the Cancel button subview. This answer seems to do a great job of explaining how to do that in Objective C, but I'm having trouble translating it into C# within the Xamarin.Forms framework.

3

3 Answers

4
votes

Create a new custom renderer for iOS. Something like CustomSearchBarRenderer and subclass the Xamarin's original SearchBarRenderer

public class CustomSearchBarRenderer : SearchBarRenderer { }

I'd probably try to override OnElementChanged method and set the custom title after the base class has done all the work. Like this:

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

    var cancelButton = Control.FindDescendantView<UIButton>();
    cancelButton.Title = "Whatever";
}

Edit: Please be aware that the cancelButton might get recreated at some point so you might have to set the title at some other point too. However, this should be a good starting point.

You can also take a look at the current SearchBarRenderer implementation here.

2
votes

I combined the answers and set the button text on each event which is needed. I also fixed the showing and hiding of the cancel button (see here):

using FestivalHolledauApp.iOS;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using System.Linq;

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

            // Fixing Cancel button
            if (e.NewElement != null)
            {             
                this.Control.TextChanged += (s, ea) =>
                {
                    this.Control.ShowsCancelButton = true;
                    SetCancelButtonText();
                };

                this.Control.OnEditingStarted += (s, ea) => //when control receives focus
                {
                    this.Control.ShowsCancelButton = true;
                    SetCancelButtonText();
                };

                this.Control.OnEditingStopped += (s, ea) => //when control looses focus 
                {
                    this.Control.ShowsCancelButton = false;
                };
            }
        }

        private void SetCancelButtonText()
        {
            var cancelButton = Control.Descendants().OfType<UIButton>().FirstOrDefault();
            if (cancelButton != null)
            {
                cancelButton.SetTitle("Schließen", UIControlState.Normal);
            }
        }
    }
}
0
votes

I've come over the same issue with ...

  • the "Cancel" button in a UISearchBar
  • the "Back" button to prior pages without title
  • context menu actions like "Cut", "Copy" and "Paste"
  • the "Done" buttons on date pickers and multiline editors

Everything else I got localized with resource based localization.

resource based localization

There are a lot of hacks out there finding the native buttons and setting texts manually but I knew this was not the way it was meant to be. So I digged deeper and found the following excellent article from Gerald Versluis:

For me, this just meant to add the following block to my Info.plist:

    <key>CFBundleLocalizations</key>
    <array>
        <string>en</string>
        <string>de</string>
    </array>

With this, iOS automatically translated all the UI elements for the current system culture (without adding these text to any resource files).

SearchBar BackButton