xamlxamarinxamarin.formstabbedpage

How to center Tabbed Page Tab Icons and/or text in XAML?


I've encountered a problem working with Xamarin Forms for Android. I've created a TabbedPage with ContentPages for displaying different content. At the bottom, there is a navigational tab bar, which should have icons displayed. What is the way to center the tab bar icons or align the displayed content, so that the icon would be in the center? Currently, the text is below the horizontal centerline of the individual tab bar item while the icon is above it:

enter image description here

This project is for Android only

<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:mc ="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         x:Class="RandomMovie.MainPage"
         xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
         xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView"
        xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
        xmlns:windows="clr-namespace:Xamarin.Forms.PlatformConfiguration.WindowsSpecific;assembly=Xamarin.Forms.Core">




<ContentPage  Padding="0,-15,0,0" IconImageSource="@drawable/search_icon.png">
    
    <CollectionView ItemsSource="{Binding Watchlist}" Margin="0" >
        <CollectionView.ItemsLayout>
            <GridItemsLayout Orientation="Vertical"
                    Span="2" />
        </CollectionView.ItemsLayout>
        <CollectionView.ItemTemplate>
            
            <DataTemplate>
                <Grid Margin="0" Padding="5,5,5,0">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="auto" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="auto" />
                    </Grid.ColumnDefinitions>

                    <Image Margin="0"
                           HeightRequest="300"
                           WidthRequest="170" Aspect="AspectFit"
                           VerticalOptions="End">
                        <Image.Source >
                            <UriImageSource 
                                Uri="{Binding poster_path}"
                                 CacheValidity="14" 
                                 CachingEnabled="true"
                                >

                            </UriImageSource>
                        </Image.Source>
                    </Image>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</ContentPage>

<ContentPage Title="Search">
    <ScrollView>
        <ListView  x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        
    </ScrollView>
</ContentPage>

<ContentPage Title="Ratings">
</ContentPage>

Solution

  • There is no way to this from XAML code only.

    To achieve this on Android you need to get access to the native BottomNavigationView and change LabelVisibilityMode to LabelVisibilityMode.LabelVisibilityUnlabeled

    Here's how I did in one of my apps using a custom renderer for TabbedPage:

    using System.Collections.Generic;
    using System.Linq;
    using Android.Content;
    using Android.Views;
    using SampleApp.Droid.Renderers;
    using Google.Android.Material.BottomNavigation;
    using Plugin.Badge.Droid;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.Android;
    using static Google.Android.Material.BottomNavigation.BottomNavigationView;
    using View = Android.Views.View;
    
    [assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedPageRenderer))]
    namespace SampleApp.Droid.Renderers
    {
        public class CustomTabbedPageRenderer : TabbedPageRenderer
        {
            public CustomTabbedPageRenderer(Context context) : base(context)
            {
            }
    
            protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
            {
                base.OnElementChanged(e);
    
                if (e.NewElement != null)
                {
                    IEnumerable<View> children = GetAllChildViews(ViewGroup);
                    BottomNavigationView bottomNavBar = (BottomNavigationView)children.SingleOrDefault(view => view is BottomNavigationView);
                    
                    if (bottomNavBar != null)
                        bottomNavBar.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityUnlabeled;
                }
            }
    
            private IEnumerable<View> GetAllChildViews(View view)
            {
                if (!(view is ViewGroup group))
                    return new List<View> { view };
    
                List<View> result = new List<View>();
                int childCount = group.ChildCount;
                
                for (int i = 0; i < childCount; i++)
                {
                    View child = group.GetChildAt(i);
                    List<View> childList = new List<View> { child };
                    childList.AddRange(GetAllChildViews(child));
                    result.AddRange(childList);
                }
    
                return result.Distinct();
            }
        }
    }