Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

How fix this problem?

KymusKymus Member ✭✭
edited October 7 in Xamarin.Forms

I want to create custom TabbedPage, but I have error: System.NullReferenceException: 'Object reference not set to an instance of an object.'

How I can fix it?

This is my custom TabbedPage code:

[assembly: ExportRenderer(typeof(CustomTabbedPage), typeof(CustomTabbedPageRenderer))]
namespace App.Droid.CustomRenders
{
[Obsolete]
class CustomTabbedPageRenderer : TabbedRenderer
{
Xamarin.Forms.TabbedPage tabbedPage;
BottomNavigationView bottomNavigationView;
Android.Views.IMenuItem lastItemSelected;
private bool firstTime = true;
int lastItemId = -1;
public CustomTabbedPageRenderer(Context context) : base(context)
{
}

    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TabbedPage> e)
    {
        base.OnElementChanged(e);

        if (e.NewElement != null)
        {
            tabbedPage = e.NewElement as CustomTabbedPage;
            bottomNavigationView = (GetChildAt(0) as Android.Widget.RelativeLayout).GetChildAt(1) as BottomNavigationView;
            bottomNavigationView.NavigationItemSelected += BottomNavigationView_NavigationItemSelected;

            //Call to remove animation
            SetShiftMode(bottomNavigationView, false, false);

            //Call to change the font
            ChangeFont();
        }

        if (e.OldElement != null)
        {
            bottomNavigationView.NavigationItemSelected -= BottomNavigationView_NavigationItemSelected;
        }


    }

    //Change Tab font
    void ChangeFont()
    {
        var fontFace = Typeface.CreateFromAsset(Context.Assets, "gilsansultrabold.ttf");
        var bottomNavMenuView = bottomNavigationView.GetChildAt(0) as BottomNavigationMenuView;

        for (int i = 0; i < bottomNavMenuView.ChildCount; i++)
        {
            var item = bottomNavMenuView.GetChildAt(i) as BottomNavigationItemView;
            var itemTitle = item.GetChildAt(1);

            var smallTextView = ((TextView)((BaselineLayout)itemTitle).GetChildAt(0));
            var largeTextView = ((TextView)((BaselineLayout)itemTitle).GetChildAt(1));

            lastItemId = bottomNavMenuView.SelectedItemId;

            smallTextView.SetTypeface(fontFace, TypefaceStyle.Bold);
            largeTextView.SetTypeface(fontFace, TypefaceStyle.Bold);

            //Set text color
            var textColor = (item.Id == bottomNavMenuView.SelectedItemId) ? tabbedPage.On<Xamarin.Forms.PlatformConfiguration.Android>().GetBarSelectedItemColor().ToAndroid() : tabbedPage.On<Xamarin.Forms.PlatformConfiguration.Android>().GetBarItemColor().ToAndroid();
            smallTextView.SetTextColor(textColor);
            largeTextView.SetTextColor(textColor);
        }
    }

    //Remove tint color
    protected override void OnLayout(bool changed, int l, int t, int r, int b)
    {
        base.OnLayout(changed, l, t, r, b);

        if (bottomNavigationView != null)
        {
            bottomNavigationView.ItemIconTintList = null;
        }

        if (firstTime && bottomNavigationView != null)
        {
            for (int i = 0; i < Element.Children.Count; i++)
            {
                var item = bottomNavigationView.Menu.GetItem(i);
                if (bottomNavigationView.SelectedItemId == item.ItemId)
                {
                    SetupBottomNavigationView(item);
                    break;
                }
            }
            firstTime = false;
        }

    }

    void BottomNavigationView_NavigationItemSelected(object sender, BottomNavigationView.NavigationItemSelectedEventArgs e)
    {
        var bottomNavMenuView = bottomNavigationView.GetChildAt(0) as BottomNavigationMenuView;
        var normalColor = tabbedPage.On<Xamarin.Forms.PlatformConfiguration.Android>().GetBarItemColor().ToAndroid();
        var selectedColor = tabbedPage.On<Xamarin.Forms.PlatformConfiguration.Android>().GetBarSelectedItemColor().ToAndroid();

        if (lastItemSelected != null)
        {
            lastItemSelected.Icon.SetColorFilter(normalColor, PorterDuff.Mode.SrcIn);

        }

        if ($"{e.Item}" != "App")
        {
            e.Item.Icon.SetColorFilter(selectedColor, PorterDuff.Mode.SrcIn);
            lastItemSelected = e.Item;
        }

        if (lastItemId != -1)
        {
            SetTabItemTextColor(bottomNavMenuView.GetChildAt(lastItemId) as BottomNavigationItemView, normalColor);
        }

        SetTabItemTextColor(bottomNavMenuView.GetChildAt(e.Item.ItemId) as BottomNavigationItemView, selectedColor);


        SetupBottomNavigationView(e.Item);
        //this.OnNavigationItemSelected(e.Item);

        lastItemId = e.Item.ItemId;

    }


    void SetTabItemTextColor(BottomNavigationItemView bottomNavigationItemView, Android.Graphics.Color textColor)
    {
        var itemTitle = bottomNavigationItemView.GetChildAt(1);
        var smallTextView = ((TextView)((BaselineLayout)itemTitle).GetChildAt(0));
        var largeTextView = ((TextView)((BaselineLayout)itemTitle).GetChildAt(1));

        smallTextView.SetTextColor(textColor);
        largeTextView.SetTextColor(textColor);
    }


    //Adding line view
    void SetupBottomNavigationView(IMenuItem item)
    {
        int lineBottomOffset = 8;
        int lineWidth = 4;
        int itemHeight = bottomNavigationView.Height - lineBottomOffset;
        int itemWidth = (bottomNavigationView.Width / Element.Children.Count);
        int leftOffset = item.ItemId * itemWidth;
        int rightOffset = itemWidth * (Element.Children.Count - (item.ItemId + 1));
        GradientDrawable bottomLine = new GradientDrawable();
        bottomLine.SetShape(ShapeType.Line);
        bottomLine.SetStroke(lineWidth, Xamarin.Forms.Color.DarkGray.ToAndroid());

        var layerDrawable = new LayerDrawable(new Drawable[] { bottomLine });
        layerDrawable.SetLayerInset(0, leftOffset, itemHeight, rightOffset, 0);

        bottomNavigationView.SetBackground(layerDrawable);
    }


    //Remove animation
    public void SetShiftMode(BottomNavigationView bottomNavigationView, bool enableShiftMode, bool enableItemShiftMode)
    {
        try
        {
            var menuView = bottomNavigationView.GetChildAt(0) as BottomNavigationMenuView;
            if (menuView == null)
            {
                System.Diagnostics.Debug.WriteLine("Unable to find BottomNavigationMenuView");
                return;
            }
            var shiftMode = menuView.Class.GetDeclaredField("mShiftingMode");
            shiftMode.Accessible = true;
            shiftMode.SetBoolean(menuView, enableShiftMode);
            shiftMode.Accessible = false;
            shiftMode.Dispose();
            for (int i = 0; i < menuView.ChildCount; i++)
            {
                var item = menuView.GetChildAt(i) as BottomNavigationItemView;
                if (item == null)
                    continue;
                //item.SetShiftingMode(enableItemShiftMode);
                item.SetChecked(item.ItemData.IsChecked);
            }
            menuView.UpdateMenuView();
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine($"Unable to set shift mode: {ex}");
        }
    }
}

}

And my xaml code:

<var:CustomTabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

            NavigationPage.HasNavigationBar="False"
            xmlns:app="clr-namespace:App;"
                      xmlns:var="clr-namespace:App.CustomClasses"
             x:Class="App1.Pages.CarPage.TabbedMenu">
  <!--Pages can be added as references or inline-->
    <var:CustomTabbedPage.Children>
        <NavigationPage Title="Page1" BackgroundColor="White">
        <x:Arguments>
            <app:Page1 />
        </x:Arguments>
    </NavigationPage>
        <NavigationPage Title="Page2" BackgroundColor="White">
        <x:Arguments>
            <app:Page2 />
        </x:Arguments>
    </NavigationPage>
    </var:CustomTabbedPage.Children>
</var:CustomTabbedPage>

Best Answer

Answers

Sign In or Register to comment.