Using accent color as ListView selected cell color (Xamarin Forms Android)

The Xamarin Forms ListView control displays a list of items and can also indicate currently selected item. However, if you modified the base colors of your Android application the background color of the currently selected item is not matching the Android accent color.
This can be achieved by a custom cell renderer which will set the background color of the list view selected Cell to the accent color in case that the Cell is selected.

Here is the code:

public class CustomCellRenderer : ViewCellRenderer
{

    private Dictionary _cells = new Dictionary();

    protected override global::Android.Views.View GetCellCore(Cell item, global::Android.Views.View convertView, ViewGroup parent, Context context)
    {
        // Generate the View for the cell
        var view = base.GetCellCore(item, convertView, parent, context);
        bool isSelected;

        // Determine if the cell is selected by checking if the owner ListView SelectedItem property matches the cell BindingContext
        // Unfortunately although the cell internally tracks if it is selected or not, we can not access that information because its private
        Xamarin.Forms.ListView lv = item.Parent as Xamarin.Forms.ListView;
        if (lv != null)
            isSelected = lv.SelectedItem == item.BindingContext;
        else
            isSelected = false;

        // Store the current cell selection status
        _cells[item] = (view, isSelected);

        // Set the color of the underlying view immediately
        SetColor(view, isSelected);
        return view;
    }

    protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnCellPropertyChanged(sender, e);
        if(e.PropertyName == "IsSelected")
        {
            // Unfortunately although the cell internally tracks if it is selected or not, we can not access that information because its private
            // However we can catch the firing of the event when the cell IsSelected property changes
            var item = _cells[(Cell)sender];
            // Set the color of the underlying view
            SetColor(item.view, !item.selected);
            // Invert the selected flag
            _cells[(Cell)sender] = (item.view, !item.selected);
        }
    }

    private void SetColor(global::Android.Views.View view, bool isSelected)
    {
        global::Android.Graphics.Color backgroundColor;
        if (isSelected)
        {
            // Use the accent color if the cell is selected
            backgroundColor = new global::Android.Graphics.Color(global::Android.Support.V4.Content.ContextCompat.GetColor(view.Context, Resource.Color.colorAccent));
        }
        else
        {
            backgroundColor = global::Android.Graphics.Color.Transparent;
        }
        view.SetBackgroundColor(backgroundColor);
    }

}

Leave a Reply

Your email address will not be published. Required fields are marked *