简体   繁体   中英

How can I style the Xamarin.Forms SearchBar in iOS?

I'm trying to style the Xamarin.Forms SearchBar and I can see that there is a BackgroundColor property, however no matter what I set, the property is ignored in iOS.

Is it even possible to customize the Xamarin.Forms SearchBar in iOS (and how)?

I couldn't get the accepted answer to work unfortunately. The below code does work for me though for iOS. Note that OnElementChanged rather than Draw seems to be the preferred place to put this sort of thing in custom renderers.

using MonoTouch.UIKit;

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly:ExportRenderer( typeof(MyNamespace.MySearchBar), typeof(MyNamespace.iOS.MySearchBarRenderer_iOS))]


namespace MyNamespace.iOS
{
    public class MySearchBarRenderer_iOS : SearchBarRenderer
    {
        protected override void OnElementChanged( ElementChangedEventArgs<SearchBar> args )
        {
            base.OnElementChanged( args );

            UISearchBar bar = (UISearchBar)this.Control;

            bar.AutocapitalizationType = UITextAutocapitalizationType.None;
            bar.AutocorrectionType = UITextAutocorrectionType.No;
            bar.BarStyle = UIBarStyle.Default;
            bar.BarTintColor = UIColor.Green;
            bar.KeyboardType = UIKeyboardType.ASCIICapable;
        }
    }
}

As near as I can tell, Xamarin.Forms does not property implement the BackgroundColor property, or it is broken. The UISearchBar property closest to a true background color is BarTint, which is not set by XForms.

To solve this, I took the comments to heart and created my own custom SearchBar with a custom renderer in order to extend the BarTint property as well as a few other things I wanted.

Note: In order to use custom renderers make sure you are updated to Xamarin.Forms 1.1.1.6206 or greater. To update your platform version use NuGet in Visual Studio, or the built in package manager in XamarinStudio.

You will need two classes, the first one is CustomSearchBar, which is what the UI will use to hold the custom properties. It goes in the shared or portable class library. :

using Xamarin.Forms;

namespace App1
{
    public class CustomSearchBar : SearchBar
    {
        // Use Bindable properties to maintain XAML binding compatibility

        public static readonly BindableProperty BarTintProperty = BindableProperty.Create<CustomSearchBar, Color?>(p => p.BarTint, null);
        public Color? BarTint
        {
            get { return (Color?)GetValue(BarTintProperty); }
            set { SetValue(BarTintProperty, value); }
        }

        public static readonly BindableProperty SearchStyleProperty = BindableProperty.Create<CustomSearchBar, string>(p => p.SearchStyle, "Default");
        public string SearchStyle
        {
            get { return (string)GetValue(SearchStyleProperty); }
            set { SetValue(SearchStyleProperty, value); }
        }

        public static readonly BindableProperty BarStyleProperty = BindableProperty.Create<CustomSearchBar, string>(p => p.BarStyle, "Default");
        public string BarStyle
        {
            get { return (string)GetValue(BarStyleProperty); }
            set { SetValue(BarStyleProperty, value); }
        }

    }
}

The second class is the custom renderer itself, which has access to the native UISearchButton control. This class goes in the iOS project:

using System;
using System.Drawing;
using App1;
using App1.iOS;
using MonoTouch.UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRendererAttribute(typeof(CustomSearchBar), typeof(CustomSearchBarRenderer))]
namespace App1.iOS
{
    public class CustomSearchBarRenderer : SearchBarRenderer
    {
        // There might be a better place for this, but I don't know where it is
        public override void Draw(RectangleF rect)
        {
            var csb = (CustomSearchBar) Element;
            if (csb.BarTint != null)
                Control.BarTintColor = csb.BarTint.GetValueOrDefault().ToUIColor();
            Control.BarStyle = (UIBarStyle)Enum.Parse(typeof(UIBarStyle), csb.BarStyle);
            Control.SearchBarStyle = (UISearchBarStyle)Enum.Parse(typeof(UISearchBarStyle), csb.BarStyle);

            base.Draw(rect);
        }
    }
}

The code is a little rough, but hopefully you get the idea.

A couple of additional notes:

  • None of this works without the ExportRendererAttribute, so don't leave that off.
  • I had to make the BarTint nullable (because it is null be default and Color.Default results in black).
  • I override Draw() even though I'm not technically drawing anything because I don't know where else to put the code. The Control and Element properties are not available in the constructor. If I find a better solution, I'll try to update this example.
  • I use strings for the Enum properties, but that could probably be improved in the future.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM