Android Custom Frame Renderer Help

Hello Community,

I created a custom FRAME renderer that creates a gradient background. It works for iOS however in Android the gradient works but none of the child controls inside the frame display. Can someone tell me what I am doing wrong that causes the child controls to not display?

`

protected override void OnElementChanged( ElementChangedEventArgs<Frame> e )
    {
        base.OnElementChanged( e );

        if( e.OldElement != null || Element == null )
            return;

        Background = GetGradientDrawable();
    }

private GradientDrawable GetGradientDrawable()
    {
        Xamarin.Forms.Color[] gradientColors = new Xamarin.Forms.Color[ 2 ];
        gradientColors[ 0 ] = Card.StartColor;
        gradientColors[ 1 ] = Card.EndColor;

        int[] androidColors = new int[ gradientColors.Length ];
        for( int i = 0; i < gradientColors.Length; i++ )
        {
            Xamarin.Forms.Color temp = gradientColors[ i ];
            androidColors[ i ] = temp.ToAndroid();
        }

        GradientDrawable gradient = new GradientDrawable( GradientDrawable.Orientation.LeftRight, androidColors );
        gradient.SetCornerRadii( new float[] { Element.CornerRadius, Element.CornerRadius, Element.CornerRadius, Element.CornerRadius,
            Element.CornerRadius, Element.CornerRadius, Element.CornerRadius, Element.CornerRadius } );

        return gradient;
    }

`

Thank you in advance for the help.
Chris

Posts

  • AndreiMisiukevich_AndreiMisiukevich_ USMember ✭✭✭✭✭

    https://github.com/AndreiMisiukevich/GalleyFramework/blob/master/GalleyFramework.Droid/Renderers/GalleyBaseViewRenderer.cs

    Hi
    Check link above (My custom renderer for AbsoluteLayout)
    It's not framerenderer, but i think it can be useful

    BestRegards

  • Thank you AndreiMisiukevich_, you code worked great.

  • I also found that you can do it very easy in android using a drawable xml file like this;

    <?xml version="1.0" encoding="utf-8" ?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <corners android:radius="5dp" /> <gradient android:type="linear" android:startColor="#fff" android:endColor="#F5F5F5" android:centerX="0.2" android:centerY="0.3" android:angle="270" /> <stroke android:width="0.5dp" android:color="#D3D3D3" /> </shape>

    Then in the custom render like this;

    `

    protected override void OnElementChanged( ElementChangedEventArgs e )
    {
    base.OnElementChanged( e );

            ViewGroup.SetBackgroundResource(Resource.Drawable.shadow_drawable);
        }
    

    `

  • batmacibatmaci DEMember ✭✭✭✭✭

    @AndreiMisiukevich_ said:
    https://github.com/AndreiMisiukevich/GalleyFramework/blob/master/GalleyFramework.Droid/Renderers/GalleyBaseViewRenderer.cs

    Hi
    Check link above (My custom renderer for AbsoluteLayout)
    It's not framerenderer, but i think it can be useful

    BestRegards

    your link is dead. can you post your solution please?

  • AndreiMisiukevich_AndreiMisiukevich_ USMember ✭✭✭✭✭

    @batmaci Hi, sure

    `using Xamarin.Forms.Platform.Android;
    using Xamarin.Forms;
    using GalleyFramework.Views;
    using GalleyFramework.Droid.Renderers;
    using GalleyFramework.Extensions;
    using Android.Content;
    using Android.Runtime;

    [assembly: ExportRenderer(typeof(GalleyBaseView), typeof(GalleyBaseViewRenderer))]
    namespace GalleyFramework.Droid.Renderers
    {
    [Preserve(AllMembers = true)]
    public class GalleyBaseViewRenderer : VisualElementRenderer
    {
    public GalleyBaseViewRenderer(Context context) : base(context)
    {
    }

        protected override void OnElementChanged(ElementChangedEventArgs<GalleyBaseView> e)
        {
            base.OnElementChanged(e);
            e.OldElement.NotNull().Then(() => e.OldElement.BackgroundRedrawingInvoked -= Invalidate);
            e.NewElement.NotNull().Then(() => e.NewElement.BackgroundRedrawingInvoked += Invalidate);
        }
    
        protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
        {
            var colorFrom = Element.BackgroundGradientColorFrom;
            var colorTo = Element.BackgroundGradientColorTo;
    
            if (colorFrom.HasValue && colorTo.HasValue)
            {
                var startColor = colorFrom.GetValueOrDefault().ToAndroid();
                var endColor = colorTo.GetValueOrDefault().ToAndroid();
    
                var width = 0;
                var height = Height;
                if (Element.IsHorizontalGradientBackground)
                {
                    width = Width;
                    height = 0;
                }
    
                using (var gradient = new Android.Graphics.LinearGradient(
                    0, 0, width, height,
                    startColor,
                    endColor,
                    Android.Graphics.Shader.TileMode.Mirror))
                {
    
                    using (var paint = new Android.Graphics.Paint { Dither = true })
                    {
                        paint.SetShader(gradient);
                        canvas.DrawPaint(paint);
                    }
                }
            }
            base.DispatchDraw(canvas);
        }
    }
    

    }`

  • batmacibatmaci DEMember ✭✭✭✭✭

    @AndreiMisiukevich_ thanks for your reply. i was looking for a solution for my this question, i thought maybe your render had it. could you kindly check my question see if you can help? thanks

    https://forums.xamarin.com/discussion/127245/how-to-setonclicklistener-in-framerenderer

Sign In or Register to comment.