3

I am a beginner in Xamarin and trying to use TabbedPage for my application. When I used TabbedPage and set the icons, it works fine.

enter image description here

Then I set the TabbedPage position to bottom using below link

https://learn.microsoft.com/en-us/xamarin/xamarin-forms/platform/android/tabbedpage-toolbar-placement-color

However, when I run the application, the TabbedPage icons are not visible and even the width is too long for one Tab

enter image description here

Below is my XAML code:

<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="//xamarin.com/schemas/2014/forms"
        xmlns:x="//schemas.microsoft.com/winfx/2009/xaml"
        xmlns:views="clr-namespace:App5.Views"
        x:Class="App5.Views.MainPage"
        BarBackgroundColor="LightYellow"
        BarTextColor="Black"
        xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
        android:TabbedPage.ToolbarPlacement="Bottom"
        android:TabbedPage.BarItemColor="Black"
        android:TabbedPage.BarSelectedItemColor="Red">
<TabbedPage.Children>
    <NavigationPage Title="Tab1" Icon="Tab1.png">
        <x:Arguments>
            <views:ItemsPage />
        </x:Arguments>
    </NavigationPage>
    <NavigationPage Title="Tab2" Icon="Tab2.png">
        <x:Arguments>
            <views:AboutPage />
        </x:Arguments>
    </NavigationPage>
    <NavigationPage Title="Tab3" Icon="Tab3.png">
        <x:Arguments>
            <views:AboutPage />
        </x:Arguments>
    </NavigationPage>
    <NavigationPage Title="Tab4" Icon="Tab4.png">
    <x:Arguments>
        <views:AboutPage />
    </x:Arguments>
</NavigationPage>
</TabbedPage.Children>

Can anyone please help me on this?

User5590
  • 1,383
  • 6
  • 26
  • 61

2 Answers2

1

I think there may be an issue with the space between the tab when it is selected. You need to disable the zooming effect when the tab is selected.

Create the custom tab reader to disable the zooming effect for Android.

BottomTabbedPageRenderer.cs

  [assembly: ExportRenderer(typeof(TabbedPage), typeof(BottomTabbedPageRenderer))]
namespace Droid.Renderer

{
    public class BottomTabbedPageRenderer : TabbedPageRenderer
    {
    public BottomTabbedPageRenderer(Context context) : base(context)
    {
    }

    protected override void OnLayout(bool changed, int l, int t, int r, int b)
    {
        base.OnLayout(changed, l, t, r, b);
        try
        {
            var children = GetAllChildViews(ViewGroup);

            if (children.SingleOrDefault(x => x is BottomNavigationView) is BottomNavigationView bottomNav)
            {

                try
                {
                    if (!(bottomNav.GetChildAt(0) is BottomNavigationMenuView menuView))
                    {
                        System.Diagnostics.Debug.WriteLine("Unable to find BottomNavigationMenuView");
                        return;
                    }


                    var shiftMode = menuView.Class.GetDeclaredField("mShiftingMode");

                    shiftMode.Accessible = true;
                    shiftMode.SetBoolean(menuView, false);
                    shiftMode.Accessible = false;
                    shiftMode.Dispose();


                    for (int i = 0; i < menuView.ChildCount; i++)
                    {
                        if (!(menuView.GetChildAt(i) is BottomNavigationItemView item))
                            continue;

                        item.SetShiftingMode(false);
                        item.SetChecked(item.ItemData.IsChecked);

                    }

                    menuView.UpdateMenuView();
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"Unable to set shift mode: {ex}");
                }

            }

        }
        catch (Exception e)
        {
            Console.WriteLine($"Error setting ShiftMode: {e}");
        }
    }

    private List<View> GetAllChildViews(View view)
    {
        if (!(view is ViewGroup group))
        {
            return new List<View> { view };
        }

        var result = new List<View>();

        for (int i = 0; i < group.ChildCount; i++)
        {
            var child = group.GetChildAt(i);

            var childList = new List<View> { child };
            childList.AddRange(GetAllChildViews(child));

            result.AddRange(childList);
        }

        return result.Distinct().ToList();
    }
}
}

MyTabPage.xaml

<?xml version="1.0" encoding="UTF-8"?>
<TabbedPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    BarBackgroundColor="LightYellow"
    BarTextColor="Black"
    xmlns:views="clr-namespace:Demo"
    xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
    android:TabbedPage.ToolbarPlacement="Bottom"
    x:Class="Demo.MyTabPage">
    <TabbedPage.Children>
        <NavigationPage
            Title="Tab1"
            Icon="dashboard_selected.png">
            <x:Arguments>
                <views:MainPage />
            </x:Arguments>
        </NavigationPage>
        <NavigationPage
            Title="Tab2"
            Icon="dashboard.png">
            <x:Arguments>
                <views:MainPage />
            </x:Arguments>
        </NavigationPage>
        <NavigationPage
            Title="Tab3"
            Icon="error_alert.png">
            <x:Arguments>
                <views:MainPage />
            </x:Arguments>
        </NavigationPage>
        <NavigationPage
            Title="Tab4"
            Icon="menu.png">
            <x:Arguments>
                <views:MainPage />
            </x:Arguments>
        </NavigationPage>
    </TabbedPage.Children>
</TabbedPage>

I put all the images resources in the drawable folder with xhdpi,mdpi,xxhdpi,xxxhdpi with the same name and In my case, it is working fine.

Demo

Jaymin
  • 2,879
  • 3
  • 19
  • 35
  • Thanks for your answer. I have implemented the same and the width was properly set, but do you have any idea about icons as well, because they are still not visible – User5590 Jan 28 '19 at 13:35
  • Remove `android:TabbedPage.BarItemColor="Black" android:TabbedPage.BarSelectedItemColor="Red">` and try – Jaymin Jan 28 '19 at 14:50
  • @User5590, I have used your XAML code and tried. It is working. I have removed `android:TabbedPage.BarItemColor="Black" android:TabbedPage.BarSelectedItemColor="Red">` and is working fine. Please check my updated answer. – Jaymin Jan 29 '19 at 04:57
  • Thank you for your answer, let me check from my side and will let you know the result – User5590 Jan 29 '19 at 05:02
  • I tried that but still the same result Can you please share your demo solution as zip? – User5590 Jan 29 '19 at 06:10
  • Where have you kept the image resources for android? – Jaymin Jan 29 '19 at 06:21
  • I just copied the provided icons in ios project (tab_feed, tab_about) to android Drawable folder and guess what. I was able to see icons at bottom as well. – User5590 Jan 29 '19 at 06:47
  • I just found that, the icon which I was using was of resolution 38x27, however it the existing icons are of 32x30. Is there any specific resolution required for icons? – User5590 Jan 29 '19 at 06:49
  • No, it will work. Even I have the different size of the icons. You need to put all the icons in the Android and iOS resources. If you still have an issue, just send me a code I will make it correct and send you back. – Jaymin Jan 29 '19 at 06:51
  • ohk, in my case I didn;t copy it to ios project. I just copied it to Drawable folder – User5590 Jan 29 '19 at 06:55
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/187468/discussion-between-jaymin-and-user5590). – Jaymin Jan 29 '19 at 06:56
1

As @User5590 and @Jaymin mentioned in Jaymin's answer comments, it is related to tabbar icon's resolutions (I didn't need to implement custom renderer). Here's what I did:

  1. Go to this Online Android Asset Studio and in the Source section choose Image and upload your desired tabbar icon:

enter image description here

  1. Choose your tab icon's name from the left panel:

enter image description here

And download the zip file by clicking the blue icon:

enter image description here

  1. Now that we have our tab icon for all resolutions in the zip file, place them in corespondent folder in your Android project. For example move tab_icon.png in drawable-xxxhdpi folder of zip file to same folder in Android project.

Note: make sure you set the Title and Icon properties of every page, for example in first page's XAML:

Icon="tab_icon.png"

And here's the final result:

enter image description here

VahidShir
  • 2,066
  • 2
  • 17
  • 27