Xamarin.Tips – Xamarin.Forms iOS Custom TableView Section Titles

Xamarin.Forms’ TableView is a really useful control for displaying static content. However, it has some shortfalls. The one we will look at today is customizing the Section Title. Before reading ahead, I would suggest looking at your solution and assessing whether or not your TableView could be easily replaced by a ListView. I want to point this out, because ListViews have more flexibility for GroupHeader and allow you to put any control in there without having to leave your happy place that is XAML.

If that isn’t the case, keep reading; Let’s look at some simple custom renderers that can solve this problem for iOS specifically (Android to follow).

First, let’s create a custom view that inherits TableView:

ColoredTableView.cs

 public partial class ColoredTableView : TableView
    {
        public static BindableProperty GroupHeaderColorProperty = BindableProperty.Create("GroupHeaderColor", typeof(Color), typeof(ColoredTableView), Color.White);
        public Color GroupHeaderColor
        {
            get
            {
                return (Color)GetValue(GroupHeaderColorProperty);
            }
            set
            {
                SetValue(GroupHeaderColorProperty, value);
            }
        }

        public ColoredTableView()
        {
            InitializeComponent();
        }
    }

Now let’s create a renderer in our iOS project:

ColoredTableViewRenderer.cs


[assembly: ExportRenderer(typeof(ColoredTableView), typeof(ColoredTableViewRenderer))]
namespace YOUR_IOS_NAMESPACE
{
    public class ColoredTableViewRenderer : TableViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
        {
            base.OnElementChanged(e);
            if (Control == null)
                return;

            var tableView = Control as UITableView;
            var coloredTableView = Element as ColoredTableView;
            tableView.WeakDelegate = new CustomHeaderTableModelRenderer(coloredTableView);
        }

        private class CustomHeaderTableModelRenderer : UnEvenTableViewModelRenderer
        {
            private readonly ColoredTableView _coloredTableView;
            public CustomHeaderTableModelRenderer(TableView model) : base(model)
            {
                _coloredTableView = model as ColoredTableView;
            }
            public override UIView GetViewForHeader(UITableView tableView, nint section)
            {
                return new UILabel()
                {
                    Text = TitleForHeader(tableView, section),
                    TextColor = _coloredTableView.GroupHeaderColor.ToUIColor(),
                    TextAlignment = UITextAlignment.Center
                };
            }
        }
    }
}

Basically what we are doing is overriding the WeakDelegate of the native UITableView that is under the Xamarin.Forms TableView. That WeakDelegate is of type TableViewModelRenderer which also inherits the UITableViewSource and holds our native overrides for getting cell heights, etc. Note that this inherits NOT TableViewModelRenderer, but UnEvenTableViewRenderer. This is because my TableView has set HasUnevenRows to true. This is a business rule for my application, but if you aren’t, then you can use the default TableViewModelRenderer.

The important piece is the override of GetViewForHeader. We override this in order to create a custom label that can use the properties and styles we need!

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

8 thoughts on “Xamarin.Tips – Xamarin.Forms iOS Custom TableView Section Titles”

  1. Hey Alex,

    Great post.
    I’m emailing you as I’m a little confused with the use of the tableView variable in your source code for the iOS Renderer.
    tableView.WeakDelegate = new CustomHeaderTableModelRenderer(coloredTableView);
    ^^
    Where is the variable tableView defined?
    Is it inherited or is it initialized elsewhere?

    Again great post found it really insightful

    Kind Regards,

    John

    Like

  2. Hi Alex,
    Great post, was long looking for a solution how to do this!
    I’m having one issue though: When tapping on the floating section headers, the event is propagated to the underlying table cell and triggers a tap on the cell. Is there any way to avoid this (i.e. nothing should happen when tapping on the section header)?
    I’ve tried assigning an empty UITapGestureRecognizer to the UILabel created in CustomHeaderTableModelRenderer.GetViewForHeader() but that didn’t solve it unfortunately.
    Thanks a lot,
    Franz

    Like

  3. Hi Alex,
    I didn’t want to replace the header view with a new UILabel because I wanted to keep the iOS defaults (font size, margins, etc.). So in the TableViewRenderer I called Control.GetHeaderView(i) for each of my sections and changed their TextLabel.TextColor directly. I did this in an overridden Draw method because I couldn’t find any other method that would have the header views ready. This strategy worked, except when I scrolled the TableView and a section header went out of view—when I scrolled it back into view, it went back to its original color. Any thoughts on this? Perhaps I should be doing these changes in some other method, but I don’t know which one.
    Thanks!

    Like

Leave a comment