Xamarin.Forms - Hiding label on the TabbedPage tabs (Part I - Android)
In my previous post I have explained how to deal with the selected and unselected state of the TabbedPage
tabs. This post will be a continuation on the topic of TabbedPage
customisation. I will show you how to remove labels from the tabs on Android.
Prerequisites
- You will need to update Android Support libraries to 28.0.0.1
- You will need to set Target Framework to Android Pie (9.0)
Implementation
Unfortunately, there's no property exposed on the TabbedPage
that controls the visibility of the tabs, therefore we will need to create an Effect
and write a bit of platform specific code.
In the platform-independent project (the .NET Standard project with Xamarin.Forms nuget package installed in it aka the UI project) create a RoutingEffect
using Xamarin.Forms;
namespace TabbedPagePlayground.UI.Effects
{
public class HideTabLabelsEffect : RoutingEffect
{
public HideTabLabelsEffect()
: base($"AppEffects.{nameof(HideTabLabelsEffect)}")
{
}
}
}
In the Android project create a PlatformEffect
using System.Linq;
using Android.Support.Design.BottomNavigation;
using Android.Support.Design.Widget;
using TabbedPagePlayground.Droid.Effects;
using TabbedPagePlayground.Droid.Extensions;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms.Platform.Android.AppCompat;
[assembly: ExportEffect(typeof(HideTabLabelsEffect), nameof(HideTabLabelsEffect))]
namespace TabbedPagePlayground.Droid.Effects
{
public class HideTabLabelsEffect : PlatformEffect
{
protected override void OnAttached()
{
var renderer = (Control ?? Container) as TabbedPageRenderer;
var children = renderer?.ViewGroup?.RetrieveAllChildViews();
if (children?.FirstOrDefault(x => x is BottomNavigationView) is BottomNavigationView bottomNav)
{
bottomNav.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityUnlabeled;
}
}
protected override void OnDetached()
{
}
}
}
In the above code we're setting the LabelVisibilityMode
property of the BottomNavigationView
to LabelVisibilityMode.LabelVisibilityUnlabeled
, which according to the official Android docs will hide the labels:
Label is not shown on any navigation items.
Let me shed some light on the code that is responsible for retrieving the BottomNavigationView
. We start from casting Control
and/or Container
property of the PlatformEffect
onto TabbedPageRenderer
. Then we use the ViewGroup
property
A ViewGroup is a special view that can contain other views (called children.) The view group is the base class for layouts and views containers.
to drill down into the children of our rendered view using the RetrieveAllChildViews
extension method (code below). Once we have all the children, we then look in that collection for a child of type BottomNavigationView
. Then, it's a simple as setting the LabelVisibilityMode
flag.
Extension method code:
using System.Collections.Generic;
using System.Linq;
using Android.Views;
namespace TabbedPagePlayground.Droid.Extensions
{
public static class ViewExtensions
{
public static List<View> RetrieveAllChildViews(this View view)
{
if (!(view is ViewGroup group))
{
return new List<View> { view };
}
var result = new List<View>();
for (var i = 0; i < group.ChildCount; i++)
{
var child = group.GetChildAt(i);
var childList = new List<View> { child };
childList.AddRange(RetrieveAllChildViews(child));
result.AddRange(childList);
}
return result.Distinct().ToList();
}
}
}
The sample code for the above can be found in this github repo: https://github.com/Progrunning/TabbedPagePlayground
If you haven't registered Effects
before (read more about the ResolutionGroupName
attribute), please do so now. Otherwise, your code in the PlatformEffect
won't work. I tend to put the ResolutionGroupName
attribute inside of main MainLauncher
activity
using Android.App;
using Android.Content.PM;
using Android.OS;
using TabbedPagePlayground.UI;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Resource = Android.Resource;
[assembly: ResolutionGroupName("AppEffects")] // <-- Here
namespace TabbedPagePlayground.Droid
{
[Activity(Label = "TabbedPagePlayground",
Icon = "@mipmap/icon",
Theme = "@style/MainTheme",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
}
}
That's all folks!