1

i am creating a custom renderer for Xamarin.Forms Frame control to enable extended functionality like gradient background.

for now i got it to work somehow on iOS but i am working on the android version too.

First i tried to override the SetupLayer method as it is in the default frame renderer see here, and add a sublayer there

The way i got it to work was to override Draw method and add a sublayer to the frame view and set the frame layer background to UIColor.Clear.

The issue that i got is that controls i put inside of frame and also the gradient is somehow faded like there is some layer blending stuff going on. something like .5 opacity.

Any advice how to get the Layer behind (Gradient) fully opaque?

Am i doing it wrong ?

Thanks in advance.

Update : I had removed unnecessary code from sample for not creating confusion, the issue i am facing is understand how layers blending work in iOS, as the top-layers blend with added gradient layer and look more faded than normal frame.

 //not working
 private void SetupLayer()
    {  
 *** 
 var gl = new CAGradientLayer
        {
            StartPoint = new CGPoint(0, 0),
            EndPoint = new CGPoint(1, 1),
            Frame = rect,
            Colors = new CGColor[]
            {
                    _gradinetControl.StartColor.ToCGColor(),
                    _gradinetControl.EndColor.ToCGColor()
            },
            CornerRadius = _gradinetControl.CornerRadius
        };

        Layer.BackgroundColor = UIColor.Clear.CGColor;

       Layer.InsertSublayer(gl,0);
***
}

*

//working but strange fade blending    
public override void Draw(CGRect rect)
    {           
        var gl = new CAGradientLayer
        {
            StartPoint = new CGPoint(0, 0),
            EndPoint = new CGPoint(1, 1),
            Frame = rect,
            Colors = new CGColor[]
            {
                    _gradinetControl.StartColor.ToCGColor(),
                    _gradinetControl.EndColor.ToCGColor()
            },
            CornerRadius = _gradinetControl.CornerRadius
        };

       NativeView.Layer.BackgroundColor = UIColor.Clear.CGColor;
       NativeView.Layer.InsertSublayer(gl,0);           
       base.Draw(rect);
    }
Iemanuel
  • 51
  • 1
  • 8
  • Do you mean the control you added in the Frame has a shadow around it? If so, the frame is different between iOS and android. You can try to use `HasShadow = false` to remove this effect in iOS. – Ax1le Jan 02 '18 at 06:49
  • Moreover, if I don't mistake your meaning, does this issue happen in iOS platform? – Ax1le Jan 02 '18 at 07:03
  • thanks @Land but the shadow is not a problem, if i am adding the gradient layer the frame as i presume, the top layer is blending with this layer (based on alpha channel ) and everything looks faded. What i want is just a gradient background behind everything. – Iemanuel Jan 02 '18 at 17:17
  • Could you please post some images to declare your issue. For instance, the effect you make now and the effect you want to achieve. – Ax1le Jan 03 '18 at 02:40

2 Answers2

1

I think exists a plugin for this. You can take a look there:

XFGloss

in XAML

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:xfg="clr-namespace:XFGloss;assembly=XFGloss"
             x:Class="XFGlossSample.Views.AboutPage"
             Title="XFGloss Sample App" Padding="10">

    <xfg:ContentPageGloss.BackgroundGradient>
        <xfg:Gradient Rotation="150">
            <xfg:GradientStep StepColor="White" StepPercentage="0" />
            <xfg:GradientStep StepColor="White" StepPercentage=".5" />
            <xfg:GradientStep StepColor="#ccd9ff" StepPercentage="1" />
        </xfg:Gradient>
    </xfg:ContentPageGloss.BackgroundGradient>
    ...
</ContentPage>

In code

namespace XFGlossSample.Views
{
    public class AboutPage : ContentPage
    {
        public AboutPage()
        {
            Title = "XFGloss Sample App";
            Padding = 10;

            // Manually construct a multi-color gradient at an angle of our choosing
            var bkgrndGradient = new Gradient()
            {
                Rotation = 150,
                Steps = new GradientStepCollection()
                {
                    new GradientStep(Color.White, 0),
                    new GradientStep(Color.White, .5),
                    new GradientStep(Color.FromHex("#ccd9ff"), 1)
                }
            };

            ContentPageGloss.SetBackgroundGradient(this, bkgrndGradient);

            Content = { ... }
        }
    }
}
Alessandro Caliaro
  • 5,623
  • 7
  • 27
  • 52
  • Thanks for answering @alessandro-caliaro, i know about xfgloss and is a good inspiration but that plugin not suits my needs, it is working for content pages a few more controls and view cells what i am trying is modifying the frame control to have gradient background in combination with coloured shadow. – Iemanuel Jan 01 '18 at 16:03
0

Image with the issue

Finally i found a solution on a Xamarin forum post. here It seems iOS render colors differently on layers. the workaround was to remake the cgcolor based on the xamarin forms color.

public class ExtendedFrameRenderer : FrameRenderer
{
  public override void Draw(CGRect rect)
{           
    var gl = new CAGradientLayer
    {
        StartPoint = new CGPoint(0, 0),
        EndPoint = new CGPoint(1, 1),
        Frame = rect,
        Colors = new CGColor[]
        {
                //old
                //_gradinetControl.StartColor.ToCGColor(),
                // _gradinetControl.EndColor.ToCGColor()
                //fix
                ToCGColor(__gradinetControl.StartColor),
                ToCGColor(__gradinetControl.EndColor)
        },
        CornerRadius = _gradinetControl.CornerRadius
    };

   NativeView.Layer.BackgroundColor = UIColor.Clear.CGColor;
   NativeView.Layer.InsertSublayer(gl,0);           
   base.Draw(rect);
}
    public static CGColor ToCGColor(Color color)
    {
        return new CGColor(CGColorSpace.CreateSrgb(), new nfloat[] { (float)color.R, (float)color.G, (float)color.B, (float)color.A });
    }
}
Iemanuel
  • 51
  • 1
  • 8