I figured it out thanks to this article: Xamarin.Forms Shell Custom Renderers. Note that this specifically addresses custom renderers for shell.
Here's my code (for Android):
...
// Create a custom shell renderer (MyShellRenderer in my case):
[assembly: ExportRenderer(typeof(AppShell), typeof(MyShellRenderer))]
namespace Xaminals.Droid
{
public class MyShellRenderer : ShellRenderer
{
public MyShellRenderer(Context context) : base(context)
{
}
protected override IShellTabLayoutAppearanceTracker CreateTabLayoutAppearanceTracker(ShellSection shellSection)
{
return new MyTabLayoutAppearanceTracker(this);
}
}
}
...
// Create a custom appearance tracker for tab layout (MyTabLayoutAppearanceTracker in my case):
public class MyTabLayoutAppearanceTracker : ShellTabLayoutAppearanceTracker
{
public MyTabLayoutAppearanceTracker(IShellContext shellContext) : base(shellContext)
{
}
protected override void SetColors(TabLayout tabLayout, Color foreground, Color background, Color title, Color unselected)
{
base.SetColors(tabLayout, foreground, background, title, unselected);
tabLayout.SetSelectedTabIndicatorColor(Color.Red.ToAndroid());
}
}