Search code examples
c#androidxamarinxamarin.formsxamarin.android

Bottom navigation bar gradient has unexpected appearance


I have made my application work with a Shell page because of the great control over layout appearances and the overall ease-of-use, and so far it has served me well.

The gradient should shift from the left colour to the right colour smoothly, which are both shades of blue.

A gradient drawable has been applied to the toolbar / top navigation bar, which works just as expected, but when I repeated the same process for the bottom navigation bar, some strange artifacts are occurring.

In portrait orientation, the very end of the bar is black, and then landscape orientation sees the gradient only applying to a thin strip at the top. A third artifact also makes its way when the Application's MainPage property has been set, where the confirm button that I have is somewhat seen beneath, even if the page has been dismissed by PopToRoot.

If I drag across the screen, I can see the gradient edge's going a bit off, with jagged edges.

The colours used:

#0033D5

#002394

Image of the colour artifacts taking place The landscape orientation Previous page bleeding in

Toolbar (working)

        protected override IShellToolbarAppearanceTracker CreateToolbarAppearanceTracker()
        {
            return new GradientShellToolbarAppearanceTracker(this);
        }
        public override void SetAppearance(Android.Support.V7.Widget.Toolbar toolbar, IShellToolbarTracker toolbarTracker, ShellAppearance appearance)
        {
            base.SetAppearance(toolbar, toolbarTracker, appearance);

            var gradient = new GradientDrawable(
                GradientDrawable.Orientation.LeftRight,
                new int[] { 
                    GradientShellPageColorTracker.ToolbarTopColor.ToAndroid(),
                    GradientShellPageColorTracker.ToolbarBottomColor.ToAndroid() }
                );

            toolbar.SetBackground(gradient);
        }

Bottom navigation bar (not working as intended)

        protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
        {
            return new GradientShellBottomTabBarAppearanceTracker(this, shellItem);
        }
        public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
        {
            base.SetAppearance(bottomView, appearance);

            var gradient = new GradientDrawable(
                GradientDrawable.Orientation.RightLeft,
                new int[] {
                    GradientShellPageColorTracker.BottomTabBarTopColor.ToAndroid(),
                    GradientShellPageColorTracker.BottomTabBarBottomColor.ToAndroid()
                });

            bottomView.SetBackground(gradient);
        }

Solution

  • The problem with the gradient defining code was not anything to do with the wrong methods being called, but I was incorrectly assigning colours to a colour tracker class that I created to store the TopColor and BottomColor properties of the GradientShellPage so they could be accessed from the AppearanceTracker, since I do not know how to access the Element property (to get instance variables of custom GradientShellPage) for a Tracker class as you can in the actual renderer.

    My method, of course, failed, as I wasn't even using a getter as one should (I was rushing to see results).

    This resulted in the gradient's colours being null at runtime, but the gradient object itself was not, so no errors were thrown.

    Further more, an external class is not necessary at all, as I am able to simply pass (GradientShellPage)Element through the appearance tracker’s constructor, and use the colours from there. This is the result:

    enter image description here