Shell Navigation Bar Gradient

Conor.MurphyConor.Murphy GBMember ✭✭
edited September 30 in Xamarin.Forms

Is it possible through custom rendering to add a gradient to a shell's navigation bar?

Best Answer

  • LandLuLandLu Xamurai
    Accepted Answer

    You need to create a custom renderer for Shell on each platform.

    on iOS:

    [assembly: ExportRenderer(typeof(AppShell), typeof(MyShellRenderer))]
    namespace ShellDemo.iOS
    {
        public class MyShellRenderer : ShellRenderer
        {
            protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                base.OnElementPropertyChanged(sender, e);
            }
    
            protected override IShellNavBarAppearanceTracker CreateNavBarAppearanceTracker()
            {
                return new CustomNaviBarAppearance();
            }
        }
    }
    // Custom navigation bar appearance
    public class CustomNaviBarAppearance : IShellNavBarAppearanceTracker
    {
        public void Dispose()
        {
    
        }
    
        public void ResetAppearance(UINavigationController controller)
        {
    
        }
    
        public void SetAppearance(UINavigationController controller, ShellAppearance appearance)
        {
            CAGradientLayer gradient = new CAGradientLayer();
            gradient.Frame = controller.NavigationBar.Bounds;
            gradient.Colors = new CoreGraphics.CGColor[] { UIColor.Red.CGColor, UIColor.Black.CGColor };
            gradient.StartPoint = new CoreGraphics.CGPoint(0, 0);
            gradient.EndPoint = new CoreGraphics.CGPoint(1, 0);
    
            controller.NavigationBar.SetBackgroundImage(imageFromLayer(gradient), UIBarMetrics.Default);
        }
    
        public void UpdateLayout(UINavigationController controller)
        {
    
        }
    
        UIImage imageFromLayer(CALayer layer)
        {
            UIGraphics.BeginImageContext(layer.Frame.Size);
            layer.RenderInContext(UIGraphics.GetCurrentContext());
    
            UIImage outputImage = UIGraphics.GetImageFromCurrentImageContext();
    
            UIGraphics.EndImageContext();
    
            return outputImage;
        }
    }
    

    On Android:

    [assembly: ExportRenderer(typeof(AppShell), typeof(CustomShellRenderer))]
    namespace ShellDemo.Droid
    {
        public class CustomShellRenderer : ShellRenderer
        {
            public CustomShellRenderer(Context context) : base(context)
            {
            }
    
            protected override IShellToolbarAppearanceTracker CreateToolbarAppearanceTracker()
            {
                return new CustomToolbarAppearanceTracker();
            }
        }
    }
    // Toolbar appearance
    public class CustomToolbarAppearanceTracker : IShellToolbarAppearanceTracker
    {
        public void Dispose()
        {
    
        }
    
        public void ResetAppearance(Android.Support.V7.Widget.Toolbar toolbar, IShellToolbarTracker toolbarTracker)
        {
    
        }
    
        public void SetAppearance(Android.Support.V7.Widget.Toolbar toolbar, IShellToolbarTracker toolbarTracker, ShellAppearance appearance)
        {
            toolbar.SetBackgroundResource(Resource.Drawable.custom_gradient);
        }
    }
    

    Here on Android you need to define a custom gradient shape custom_gradient.xml in Drawable:

    <?xml version="1.0" encoding="utf-8" ?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
    
      <gradient
       android:type="linear"
       android:startColor="#FF0000"
       android:endColor="#000000"
       android:angle="270"/>
    </shape>
    

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    You need to create a custom renderer for Shell on each platform.

    on iOS:

    [assembly: ExportRenderer(typeof(AppShell), typeof(MyShellRenderer))]
    namespace ShellDemo.iOS
    {
        public class MyShellRenderer : ShellRenderer
        {
            protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                base.OnElementPropertyChanged(sender, e);
            }
    
            protected override IShellNavBarAppearanceTracker CreateNavBarAppearanceTracker()
            {
                return new CustomNaviBarAppearance();
            }
        }
    }
    // Custom navigation bar appearance
    public class CustomNaviBarAppearance : IShellNavBarAppearanceTracker
    {
        public void Dispose()
        {
    
        }
    
        public void ResetAppearance(UINavigationController controller)
        {
    
        }
    
        public void SetAppearance(UINavigationController controller, ShellAppearance appearance)
        {
            CAGradientLayer gradient = new CAGradientLayer();
            gradient.Frame = controller.NavigationBar.Bounds;
            gradient.Colors = new CoreGraphics.CGColor[] { UIColor.Red.CGColor, UIColor.Black.CGColor };
            gradient.StartPoint = new CoreGraphics.CGPoint(0, 0);
            gradient.EndPoint = new CoreGraphics.CGPoint(1, 0);
    
            controller.NavigationBar.SetBackgroundImage(imageFromLayer(gradient), UIBarMetrics.Default);
        }
    
        public void UpdateLayout(UINavigationController controller)
        {
    
        }
    
        UIImage imageFromLayer(CALayer layer)
        {
            UIGraphics.BeginImageContext(layer.Frame.Size);
            layer.RenderInContext(UIGraphics.GetCurrentContext());
    
            UIImage outputImage = UIGraphics.GetImageFromCurrentImageContext();
    
            UIGraphics.EndImageContext();
    
            return outputImage;
        }
    }
    

    On Android:

    [assembly: ExportRenderer(typeof(AppShell), typeof(CustomShellRenderer))]
    namespace ShellDemo.Droid
    {
        public class CustomShellRenderer : ShellRenderer
        {
            public CustomShellRenderer(Context context) : base(context)
            {
            }
    
            protected override IShellToolbarAppearanceTracker CreateToolbarAppearanceTracker()
            {
                return new CustomToolbarAppearanceTracker();
            }
        }
    }
    // Toolbar appearance
    public class CustomToolbarAppearanceTracker : IShellToolbarAppearanceTracker
    {
        public void Dispose()
        {
    
        }
    
        public void ResetAppearance(Android.Support.V7.Widget.Toolbar toolbar, IShellToolbarTracker toolbarTracker)
        {
    
        }
    
        public void SetAppearance(Android.Support.V7.Widget.Toolbar toolbar, IShellToolbarTracker toolbarTracker, ShellAppearance appearance)
        {
            toolbar.SetBackgroundResource(Resource.Drawable.custom_gradient);
        }
    }
    

    Here on Android you need to define a custom gradient shape custom_gradient.xml in Drawable:

    <?xml version="1.0" encoding="utf-8" ?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
    
      <gradient
       android:type="linear"
       android:startColor="#FF0000"
       android:endColor="#000000"
       android:angle="270"/>
    </shape>
    
  • Conor.MurphyConor.Murphy GBMember ✭✭

    @LandLu Excellent Thank you !

Sign In or Register to comment.