Quantcast
Channel: Xamarin.Forms — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 77050

[Guide] Create a Gradient Background without Images

$
0
0

Hey,
today I accomplished the task to create Gradient Background without the use of an Image.
The task was to make it possible for the user to change the Background of the Views on Runtime! First I thought I could achive this with Images but on the long run it would have blown up the App-Size.

This is the best implementation I could come up with and the choosen Colors are persistent with the usage of the Settings Plugin form @JamesMontemagno that you can get here: Nuget

This code works for Android and iOS and you can drop it in if you want

So long Story short here's the code:

CustomRenderer in PCL:

public class GradientContentPage : ContentPage
{
    public static BindableProperty StartColorProperty = BindableProperty.Create<GradientContentPage, Color>(p => p.StartColor, Color.White);
    public static BindableProperty EndColorProperty = BindableProperty.Create<GradientContentPage, Color>(p => p.EndColor, Color.Gray);

    public Color StartColor
    {
        get { return (Color) GetValue(StartColorProperty); }
        set { SetValue(StartColorProperty, value); }
    }

    public Color EndColor
    {
        get { return (Color) GetValue(EndColorProperty); }
        set { SetValue(EndColorProperty, value); }
    }
}

To make the Colors available all over my app I create two static variables in App.cs and since I can't put a Color into the Settings I have to store them as string

So here's the code for my App.cs

public static Color StartColor;
public static Color EndColor;

public App()
{
    StartColor = StringToColor(Helpers.Settings.StartColor.Split(' , ');
    EndColor = StringToColor(Helpers.Settings.EndColor.Split(' , ');

    MainPage = new NavigationPage(new DashboardView{ StartColor = App.StartColor, EndColor = App.EndColor });
}

As you may notice I've setting the Colors for the View on creation. Sadly you have to this, because Views that inherit from ContentPage can't make us of Implicit Styles right now because of this Bug 27659

So anyway let's take a look at StringToColor

private static void StringToColor(IList<string> color)
{
    for(var i = 0; i < color.Count(); i++)
    {
        //Regex to get the color code
        color[i] = Regex.Replace(color[i], @"^\d.\d+]", "");
    }

    var a = double.Parse(color[0], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);
    var r = double.Parse(color[1], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);
    var g = double.Parse(color[2], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);
    var b = double.Parse(color[3], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);

    return Color.FromRgba(r, g, b, a);
}

Ok, I admit I'm not happy with this function and if anyone has a better idea how to achive this, please let me know! Basically this function find the Color-Code.

Alright now let's get to the platform renderers:

CustomRenderer in Android:

[assembly: ExportRenderer(typeof(GradientContentPage), typeof(GradientContentPageRenderer))]

namespace YourApp.Droid
{
    public class GradientContentPageRenderer : PageRenderer
    {
        protected override void OnVisibilityChanged(Android.Views.View changedView, ViewStates visibility)
        {
            base.OnVisibilityChanged(changedView, visibility);
            SetBackground();
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Page> page)
        {
            base.OnElementChanged(page);
            SetBackground();
        }

        private void SetBackground()
        {
            var startColor = App.StartColor.ToAndroid();
            var endColor = App.EndColor.ToAndroid();

            var colors = new int[] { startColor, endColor };

            Background = new GradientDrawable(GradientDrawable.Orientation.TopBottom, colors);
        }
    }
}

You have to overwrite both Events to get every Background in the color you wan't. It's a bit odd but this is how Forms on Android reacts and there is no (at least I haven't found one) event that gets fired everytime you switch a Page;

CustomRenderer in iOS:

[assembly: ExportRenderer(typeof(GradientContentPage), typeof(GradientContentPageRenderer))]

namespace YourApp.iOS
{
    public class GradientContentPageRenderer: PageRenderer
    {
        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);

            var gradientLayer = new CAGradientLayer
            {
                Frame = View.Bounds,
                Colors = new [] { App.StartColor.ToCGColor(), App.EndColor.ToCGColor() },
                StartPoint = new CGPoint(0, 0),
                EndPoint = new CGPoint(1, 1)
            }

            //This is needed to get every background redrawn if the color changes on runtime
            if(View.Layer.Sublayers[0].GetType() == typeof(CAGradientLayer))
            {
                View.Layer.ReplaceSublayer(View.Layer.Sublayers[0], gradientLayer);
            }
            else
            {
                View.Layer.InsertSublayer(gradientLayer, 0);
            }
        }
    }
}

For this one I have to thank @JohnBeans for his thread here on the forum: Click me

So for the Color Picking I created a view where the user can select a color and then it gets automatically drawn on runtime with the new color. But posting this would be to much for one thread. If someone is interested I can post it.


Viewing all articles
Browse latest Browse all 77050

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>