1
votes

I got 5 tabs on TabbedPage & last 2 tabs have long title name, on Android, it shows 3dots as ... when there is no more room space remaining for text.

eg.

tab 1 title - Title 1 for Tab1
tab 2 title - Title 2 for Tab2
tab 3 title - Title 3 for Tab3
 Android - Title 1 f... | Title 2 f... | Title 3 f...

But on iOS it doesn't show 3dots, it shows complete text which can even override the title of another tab. Kind of text overlapping.

Basically I want my title of TabbedPage on multi-line, I use different content pages as tabs for my TabbedPage. I can create MultiLine ContentPage n its working fine on its own. But when I set the MultiLine title content page as a tab for my TabbedPage, it only shows the first-line title.

Any solution for MultiLine TabbedPage Title on iOS like below Image from Junior Jiang - MSFT

My Current renderer code

[assembly: ExportRenderer( typeof( TabbedPage ), typeof(ExtendedTabbedPageRenderer ) )]
 namespace testBlu.iOS.Renderers
 {
   public class ExtendedTabbedPageRenderer : TabbedRenderer
   {
    public override void ViewDidAppear( bool animated )
    {
        base.ViewDidAppear( animated );
        if( TabBar.Items != null )
        {
            UITabBarItem[] tabs = TabBar.Items;
            foreach( UITabBarItem tab in tabs )
            {
                UITextAttributes selectedColor = new UITextAttributes { TextColor = UIColor.Black };
                UITextAttributes fontSize = new UITextAttributes { Font = UIFont.SystemFontOfSize( 12 )};
                tab.SetTitleTextAttributes( selectedColor, UIControlState.Normal );
                tab.SetTitleTextAttributes( fontSize, UIControlState.Normal );
            }
        }
    }
  }
}
2

2 Answers

1
votes

If need to show three dots the same with Android , here is a solution for you . Later if have solution for multi-lines will update here .

You can use Custom TabbedRenderer to implement it .

[assembly: ExportRenderer(typeof(MainPage), typeof(ExtendedTabbedPageRenderer))]
namespace AppTab3.iOS
{
    public class ExtendedTabbedPageRenderer : TabbedRenderer
    {
        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);
            var tabs = Element as TabbedPage;
            if(tabs != null)
            {
                for( int i = 0;i < TabBar.Items.Length;i++)
                {
                    if (TabBar.Items[i] == null) return;

                    if(TabBar.Items[i].Title.Length > 6)
                    {
                        string showText = TabBar.Items[i].Title;
                        TabBar.Items[i].Title = showText.Substring(0, 5) + "...";
                    }
                }
            }
        }
    }
}

Here MainPage inside code is a TabbedPagepublic partial class MainPage : TabbedPage

And here I set the limited length of TabBar Text is 6 . The Xaml is as follow :

<?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:d="http://xamarin.com/schemas/2014/forms/design"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            mc:Ignorable="d"
            xmlns:views="clr-namespace:AppTab3.Views"
            x:Class="AppTab3.Views.MainPage">

    <TabbedPage.Children>
        <NavigationPage Title="Browse">

            <NavigationPage.Icon>
                <OnPlatform x:TypeArguments="FileImageSource">
                    <On Platform="iOS" Value="tab_feed.png"/>
                </OnPlatform>
            </NavigationPage.Icon>
            <x:Arguments>
                <views:ItemsPage />
            </x:Arguments>
        </NavigationPage>

      ...

        <NavigationPage Title="Page Five Long Title Page Five Long Title">
            <NavigationPage.TitleView>
                 <Label Text="About Five Long Title" MaxLines="4"/>
            </NavigationPage.TitleView>
            <NavigationPage.Icon>
                <OnPlatform x:TypeArguments="FileImageSource">
                    <On Platform="iOS"
                        Value="tab_about.png" />
                </OnPlatform>
            </NavigationPage.Icon>
            <x:Arguments>
                <views:AboutPage />
            </x:Arguments>
        </NavigationPage>

    </TabbedPage.Children>

</TabbedPage>

The effect :

enter image description here

================================Update=============================

I have found the way to implement multiline title in tabbar item , need to modify code in TabbedRenderer as follow :

public override void ViewWillAppear(bool animated)
{
    base.ViewWillAppear(animated);
    var tabs = Element as TabbedPage;

    if (tabs != null)
    {
        for (int i = 0; i < TabBar.Items.Length; i++)
        {

            if (TabBar.Items[i] == null) continue;

            if (TabBar.Items[i].Title.Length > 6)
            {
                string[] splitTitle = TabBar.Items[i].Title.Split(" ");
                TabBar.Items[i].Title = splitTitle[0] + "\n" + splitTitle[1];

                UITabBarItem item = TabBar.Items[i] as UITabBarItem;
                UIView view = item.ValueForKey(new Foundation.NSString("view")) as UIView;
                UILabel label = view.Subviews[1] as UILabel;
                //label.Text = "Hello\nWorld!";
                label.Lines = 2;
                label.LineBreakMode = UILineBreakMode.WordWrap;

                //var frame = label.Frame;
                //label.Frame = CGRect.FromLTRB(frame.Location.X, frame.Location.Y, frame.Size.Width, frame.Size.Height + 20);
            }
        }
    }
}

The effect:

enter image description here

Note : Althouh this way can implement it , however Apple not recommands to do this . It will affect the beauty of interface ,and make the frame of Tabbar item's shape distortion .

=============================Update with shared code=======================

public override void ViewWillAppear(bool animated)
{
    base.ViewWillAppear(animated);
    var tabs = Element as TabbedPage;

    if (tabs != null)
    {
        for (int i = 0; i < TabBar.Items.Length; i++)
        {

            if (TabBar.Items[i] == null) continue;

            if (TabBar.Items[i].Title.Length > 6)
            {
                string[] splitTitle = TabBar.Items[i].Title.Split(" ");
                if (null != splitTitle[1])
                {
                    if (splitTitle[1].Length > 4)
                    {
                        string showText = splitTitle[1];
                        splitTitle[1] = showText.Substring(0, 3) + "...";
                    }
                }

                TabBar.Items[i].Title = splitTitle[0] + "\n" + splitTitle[1];

                UITabBarItem item = TabBar.Items[i] as UITabBarItem;
                UITextAttributes selectedColor = new UITextAttributes { TextColor = UIColor.Black };
                UITextAttributes fontSize = new UITextAttributes { Font = UIFont.SystemFontOfSize(12) };
                item.SetTitleTextAttributes(selectedColor, UIControlState.Selected);
                item.SetTitleTextAttributes(fontSize, UIControlState.Selected);

                UIView view = item.ValueForKey(new Foundation.NSString("view")) as UIView;
                UILabel label = view.Subviews[1] as UILabel;
                //label.Text = "Hello\nWorld!";
                label.Lines = 2;
                label.LineBreakMode = UILineBreakMode.WordWrap;

                //var frame = label.Frame;
                //label.Frame = CGRect.FromLTRB(frame.Location.X, frame.Location.Y, frame.Size.Width, frame.Size.Height + 10);
            }
        }
    }
}
-2
votes

I think the most simple way (i.e, avoiding a custom renderer) would be to use a TitleView

Here's the official Microsoft sample. https://docs.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/navigation-titleview/

Here's a blog post. https://www.andrewhoefling.com/Blog/Post/xamarin-forms-title-view-a-powerful-navigation-view

In that TitleView you can use a Label and set the LineBreakMode property.