4

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.

jbyrd
  • 5,287
  • 7
  • 52
  • 86

3 Answers3

4

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.

Timo Salomäki
  • 7,099
  • 3
  • 25
  • 40
  • 1
    Pretty much the exact setup I have - but your `.FindDescendantView...` suggestion got me to reexamine the available methods on the Control, and I found `.Descendants`! So I'm going to try `UIButton cancelButton = Control.Descendants().OfType().FirstOrDefault();` – jbyrd Aug 18 '17 at 18:36
  • So I was able to change the text by including code in the `OnElementPropertyChanged()` method, with `UIButton cancelButton = Control.Descendants().OfType().FirstOrDefault();` and then `cancelButton.SetTitle("Custom", UIControlState.Normal);`*BUT* -- there's a bug where after the first time the cancel button appears, everytime after that, there is overlapped text where the first part of the custom text also appears just to the right of (as part of) the "x" button, - like this: https://snag.gy/SiMsu5.jpg – jbyrd Aug 21 '17 at 18:39
2

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);
            }
        }
    }
}
Suplanus
  • 1,523
  • 16
  • 30
1

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

Waescher
  • 5,361
  • 3
  • 34
  • 51