RMR
RMR

Reputation: 629

Facing issue to customize Tabbed page for IOS in xamarin.forms

I want to create this kind of design for bottom tabs

enter image description here

I am working in Xamarin.Forms, and I am facing a designing issue in iOS. I am using TabbedPage as follows:

<TabbedPage 
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="Inika.Views.BottomBar.BottomBarPages"
    xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
    android:TabbedPage.ToolbarPlacement="Bottom"
    android:TabbedPage.BarItemColor="#A9A9A9"
    android:TabbedPage.BarSelectedItemColor="Black">
</TabbedPage>

For this kind of design, I have created "TabbedRenderer"

public class TabbedPageRender_Global : TabbedRenderer
{
    public override void ViewWillAppear(bool animated)
    {
        base.ViewWillAppear(animated);
        if (TabBar == null) return;
        if (TabBar.Items == null) return;

        var tabs = Element as TabbedPage;

        //For selected Items
        UITabBarItem.Appearance.SetTitleTextAttributes(new UITextAttributes()
        {
            TextColor = UIColor.FromRGB(255, 255, 255)
        },
        UIControlState.Selected);
        UITabBar.Appearance.SelectedImageTintColor = UIColor.FromRGB(255, 255, 255);

        CGSize size = new CGSize(TabBar.Frame.Width / TabBar.Items.Length, TabBar.Frame.Height);
        UITabBar.Appearance.SelectionIndicatorImage = imageWithColor(size);

        //For unselected Items
        TabBar.UnselectedItemTintColor = UIColor.Gray;

        base.ViewWillAppear(animated);
    }

    public UIImage imageWithColor(CGSize size)
    {
        CGRect rect = new CGRect(0 , 0, size.Width, size.Height);
        UIGraphics.BeginImageContext(size);

        using (CGContext context = UIGraphics.GetCurrentContext())
        {
            context.SetFillColor(UIColor.Black.CGColor);
            context.FillRect(rect);
        }

        UIImage image = UIGraphics.GetImageFromCurrentImageContext();
        UIGraphics.EndImageContext();

        return image;
    }
}

iPad Screenshot

It looks proper in iPhone but in all iPads, it looks like below image enter image description here

It left some space from start.

CGRect rect = new CGRect(0 , 0, size.Width, size.Height);

What should I do? Please suggest me some work around.

Is this native behavior of IOS in IPad devices?

Upvotes: 0

Views: 1062

Answers (1)

gannaway
gannaway

Reputation: 1882

The UITraitCollection is related to the problem, although I don't know the specific details, and allowing screen rotation introduces additional challenges. The following seems to work for iPhone/iPad (and handles rotation as well):

public class CustomTabbedPageRenderer1 : TabbedRenderer
{
    private readonly UITraitCollection traitCollectionTablet = UITraitCollection.FromUserInterfaceIdiom(UIUserInterfaceIdiom.Phone);
    private readonly UITraitCollection traitCollectionPhone = UITraitCollection.FromHorizontalSizeClass(UIUserInterfaceSizeClass.Regular);

    private CGSize lastSelectionIndicatorImageSize;

    public override UITraitCollection TraitCollection
    {
        get
        {
            switch (Device.Idiom)
            {
                case TargetIdiom.Tablet:
                    return this.traitCollectionTablet;
                case TargetIdiom.Phone:
                    return this.traitCollectionPhone;
                default:
                    return base.TraitCollection;
            }
        }
    }

    public override void ViewDidLayoutSubviews()
    {
        base.ViewDidLayoutSubviews();

        if (this.lastSelectionIndicatorImageSize.Height != this.TabBar.Frame.Height ||
            this.lastSelectionIndicatorImageSize.Width != this.TabBar.Frame.Width / this.TabBar.Items.Length)
        {
            this.lastSelectionIndicatorImageSize = new CGSize(this.TabBar.Frame.Width / this.TabBar.Items.Length, this.TabBar.Frame.Height);
            this.SetSelectionIndicatorImage(this.lastSelectionIndicatorImageSize);
        }
    }

    protected override void OnElementChanged(VisualElementChangedEventArgs e)
    {
        base.OnElementChanged(e);

        if (e.NewElement != null)
        {
            //For selected Items
            UITabBarItem.Appearance.SetTitleTextAttributes(new UITextAttributes { TextColor = UIColor.White }, UIControlState.Selected);
            UITabBar.Appearance.SelectedImageTintColor = UIColor.White;

            //For unselected Items
            this.TabBar.UnselectedItemTintColor = UIColor.Gray;
        }
    }

    private void SetSelectionIndicatorImage(CGSize size)
    {
        CGRect rect = new CGRect(0, 0, size.Width, size.Height);
        UIGraphics.BeginImageContext(size);

        using (CGContext context = UIGraphics.GetCurrentContext())
        {
            context.SetFillColor(UIColor.Black.CGColor);
            context.FillRect(rect);
        }

        UIImage image = UIGraphics.GetImageFromCurrentImageContext();
        UIGraphics.EndImageContext();

        using (image)
        {
            this.TabBar.SelectionIndicatorImage = image;
        }
    }
}

Result

enter image description here

Upvotes: 1

Related Questions