2020.09.01.

Xamarin.Forms change ListView SelectedItemColor

By bence960206

This project you can find at: https://github.com/officialdoniald/Xamarin.Forms.ChangeListviewSelectedColor

We have to create a Custom Renderer for a ViewCell. So let’s create a class in the .NET Standard,/PCL Project:

https://github.com/officialdoniald/Xamarin.Forms.ChangeListviewSelectedColor/tree/master/Xamarin.Forms.ChangeLvSelectedColor/Xamarin.Forms.ChangeLvSelectedColor/CustomControl/ListViewCustomViewCell.cs/

We created a property for the SelectedItem’s color. Don’t forget: this enum is a cutom enum, we have to create it:

https://github.com/officialdoniald/Xamarin.Forms.ChangeListviewSelectedColor/blob/master/Xamarin.Forms.ChangeLvSelectedColor/Xamarin.Forms.ChangeLvSelectedColor/Helper/Enums.cs

Let’s create the platform specific code.

Android: we have to change the Android’s Theme at runtime via EventHandler.

We have to create a ViewCellRenderer class ( https://github.com/officialdoniald/Xamarin.Forms.ChangeListviewSelectedColor/blob/master/Xamarin.Forms.ChangeLvSelectedColor/Xamarin.Forms.ChangeLvSelectedColor.Android/CustomRenderers/CustomViewCellRenderer.cs ):

using System.ComponentModel;
using Android.Content;
using Android.Views;
using Xamarin.Forms;
using Xamarin.Forms.ChangeLvSelectedColor.CustomControl.ListView;
using Xamarin.Forms.ChangeLvSelectedColor.Droid.CustomRenderers;
using Xamarin.Forms.ChangeLvSelectedColor.Helper;
using Xamarin.Forms.Platform.Android;
using static Xamarin.Forms.ChangeLvSelectedColor.Droid.MainActivity;

[assembly: ExportRenderer(typeof(CustomViewCell), typeof(CustomViewCellRenderer))]
namespace Xamarin.Forms.ChangeLvSelectedColor.Droid.CustomRenderers
{
    public class CustomViewCellRenderer : ViewCellRenderer
    {
        protected override global::Android.Views.View GetCellCore(Cell item, global::Android.Views.View convertView, ViewGroup parent, Context context)
        {
            var _cellCore = base.GetCellCore(item, convertView, parent, context);

            return _cellCore;
        }

        protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
        {
            base.OnCellPropertyChanged(sender, args);

            var extendedViewCell = (CustomViewCell)sender;

            if (extendedViewCell.SelectedCellColor == ListViewSelectedBackGroundColor.CianBlue)
            {
                AndroidEvents.OnAndroidThemeChangeNeeded_Event(null, Xamarin.Forms.ChangeLvSelectedColor.Droid.Resource.Style.MainCianBlueTheme);
            }
            else if (extendedViewCell.SelectedCellColor == ListViewSelectedBackGroundColor.Normal)
            {
                AndroidEvents.OnAndroidThemeChangeNeeded_Event(null, Xamarin.Forms.ChangeLvSelectedColor.Droid.Resource.Style.MainTheme);
            }
            else if (extendedViewCell.SelectedCellColor == ListViewSelectedBackGroundColor.Transparent)
            {
                AndroidEvents.OnAndroidThemeChangeNeeded_Event(null, Xamarin.Forms.ChangeLvSelectedColor.Droid.Resource.Style.MainTransparentTheme);
            }
        }
    }
}

AndroidEvents is a static class, and in this class we have to create an event ( https://github.com/officialdoniald/Xamarin.Forms.ChangeListviewSelectedColor/blob/master/Xamarin.Forms.ChangeLvSelectedColor/Xamarin.Forms.ChangeLvSelectedColor.Android/MainActivity.cs ):

public class AndroidEvents
        {
            public static event EventHandler OnAndroidThemeChangeNeeded;

            public static void OnAndroidThemeChangeNeeded_Event(object sender, int id)
            {
                OnAndroidThemeChangeNeeded?.Invoke(sender, id);
            }
        }

This event invoke the Theme Changing at runtime. We have to call it, when the user interact with the ListView(ViewCell). We have to subscribe on this event in the MainActivity:

protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            AndroidEvents.OnAndroidThemeChangeNeeded += AndroidEvents_OnAndroidThemeChangeNeeded; ;
            LoadApplication(new App());
        }

        private void AndroidEvents_OnAndroidThemeChangeNeeded(object sender, int themeid)
        {
            RunOnUiThread(() => {
                SetTheme(themeid);
            });
        }

Finally, we have to create the Theme Shema in the style.xml (MainCianBlueTheme and MainTransparentTheme):

<?xml version="1.0" encoding="utf-8" ?>
<resources>

  <style name="MainTheme" parent="MainTheme.Base">
  </style>
  <style name="MainCianBlueTheme" parent="MainCianBlueTheme.Base">
  </style>
  <style name="MainTransparentTheme" parent="MainTransparentTheme.Base">
  </style>
  <!-- Base theme applied no matter what API -->
  <style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
    <item name="windowNoTitle">true</item>
    <!--We will be using the toolbar so no need to show ActionBar-->
    <item name="windowActionBar">false</item>
    <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette -->
    <!-- colorPrimary is used for the default action bar background -->
    <item name="colorPrimary">#2196F3</item>
    <!-- colorPrimaryDark is used for the status bar -->
    <item name="colorPrimaryDark">#1976D2</item>
    <!-- colorAccent is used as the default value for colorControlActivated
         which is used to tint widgets -->
    <item name="colorAccent">#FF4081</item>
    <!-- You can also set colorControlNormal, colorControlActivated
         colorControlHighlight and colorSwitchThumbNormal. -->
    <item name="windowActionModeOverlay">true</item>

    <item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>
  </style>

  <style name="MainCianBlueTheme.Base" parent="MainTheme">
    <item name="android:colorPressedHighlight">@color/anlistviewSelection</item>
    <item name="android:colorLongPressedHighlight">@color/anlistviewSelection</item>
    <item name="android:colorFocusedHighlight">@color/anlistviewSelection</item>
    <item name="android:colorActivatedHighlight">@color/anlistviewSelection</item>
    <item name="android:activatedBackgroundIndicator">@color/anlistviewSelection</item>
  </style>

  <style name="MainTransparentTheme.Base" parent="MainTheme">
    <item name="android:colorPressedHighlight">@color/transparentlistviewSelection</item>
    <item name="android:colorLongPressedHighlight">@color/transparentlistviewSelection</item>
    <item name="android:colorFocusedHighlight">@color/transparentlistviewSelection</item>
    <item name="android:colorActivatedHighlight">@color/transparentlistviewSelection</item>
    <item name="android:activatedBackgroundIndicator">@color/transparentlistviewSelection</item>
  </style>

  <style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
    <item name="colorAccent">#FF4081</item>
  </style>
</resources>

and their @color variablesin the colors.xml (listviewSelection, anlistviewSelection, transparentlistviewSelection):

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <color name="launcher_background">#FFFFFF</color>
  <color name="colorPrimary">#3F51B5</color>
  <color name="colorPrimaryDark">#303F9F</color>
  <color name="colorAccent">#FF4081</color>
  <color name="listviewSelection">#f17a0a</color>
  <color name="anlistviewSelection">#40E0D0</color>
  <color name="transparentlistviewSelection">#00000000</color>
</resources>

iOS: we just have to create a platform specific version of the CustomViewCell class, and gain two properties a color (https://github.com/officialdoniald/Xamarin.Forms.ChangeListviewSelectedColor/blob/master/Xamarin.Forms.ChangeLvSelectedColor/Xamarin.Forms.ChangeLvSelectedColor.iOS/CustomRenderer/CustomViewCellRenderer.cs):

using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.ChangeLvSelectedColor.CustomControl.ListView;
using Xamarin.Forms.ChangeLvSelectedColor.iOS.CustomRenderer;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(CustomViewCell), typeof(CustomViewCellRenderer))]
namespace Xamarin.Forms.ChangeLvSelectedColor.iOS.CustomRenderer
{
    public class CustomViewCellRenderer : ViewCellRenderer
    {
        public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var customViewCell = (CustomViewCell)item;

            var cell = base.GetCell(item, reusableCell, tv);

            cell.SelectedBackgroundView = new UIView { BackgroundColor = GetColor(customViewCell.SelectedCellColor) };

            //You can define a new property in the CustomViewCell class, and you can use it here:
            //This code is set the unselected background color of the ViewCell:
            //cell.BackgroundColor = GetColor(customViewCell.UnSelectedCellColor);

            return cell;
        }

        public UIColor GetColor(Helper.ListViewSelectedBackGroundColor color)
        {
            switch (color)
            {
                case Helper.ListViewSelectedBackGroundColor.CianBlue:
                    return Color.FromHex("#40E0D0").ToUIColor();
                default:
                    return Color.Transparent.ToUIColor();
            }
        }
    }
}