Forum Xamarin.Forms

how to change the shadow color of a frame?

lescperlescper Member ✭✭✭✭✭

how to change the shadow color and spread height of a frame?

Tagged:

Best Answer

  • jezhjezh Member, Xamarin Team Xamurai
    Accepted Answer

    In Android platform, we need to create file shadow.xml under Drawable folder of Android resources:

    <?xml version="1.0" encoding="utf-8" ?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <shape android:shape="rectangle">
                <solid android:color="#CABBBBBB" />
                <corners android:radius="2dp" />
            </shape>
        </item>
    
        <item
            android:left="0dp"
            android:right="0dp"
            android:top="0dp"
            android:bottom="2dp">
            <shape android:shape="rectangle">
                <solid android:color="@android:color/white" />
                <corners android:radius="2dp" />
            </shape>
        </item>
    </layer-list>
    

    And in Android Renderer, do like this:

    [assembly: ExportRenderer(typeof(MyFrame), typeof(MyAndroidRenderer))]
    namespace FormApp1.Droid
    {
        public class MyAndroidRenderer: FrameRenderer
        {
    
            Context context;
            public MyAndroidRenderer(Context context):base(context) {
    
                this.context = context;
    
            }
    
            protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
            {
                base.OnElementChanged(e);
                if (e.NewElement != null)
                {
                    ViewGroup.SetBackgroundResource(Resource.Drawable.shadow);
                }
            }
        }
    }
    

Answers

  • jezhjezh Member, Xamarin Team Xamurai
    edited December 2020

    We can create custom frame and implement the function with custom renderer on each platform .

    MyFrame

     public class MyFrame : Frame
            {
                public static readonly BindableProperty ShadowColorProperty = BindableProperty.Create(nameof(ShadowColor), typeof(Color), typeof(MyFrame), Color.Transparent);
                public static readonly BindableProperty BorderWidthProperty = BindableProperty.Create(nameof(BorderWidth), typeof(float), typeof(MyFrame));
    
                public Color ShadowColor
                {
                    get { return (Color)GetValue(ShadowColorProperty); }
                    set { SetValue(ShadowColorProperty, value); }
                }
    
    
                public float BorderWidth
                {
                    get { return (float)GetValue(BorderWidthProperty); }
                    set { SetValue(BorderWidthProperty, value); }
                }
            }
    

    Usage in xaml

    <StackLayout HorizontalOptions="Start" VerticalOptions="Start">
        <local:MyFrame 
                       HasShadow="True" 
                       ShadowColor="Red" 
                       BorderColor="Green" 
                       BorderWidth="1"/>
    </StackLayout>
    

    iOS renderer

        [assembly: ExportRenderer(typeof(MyFrame), typeof(MyRenderer))]
        namespace App2.iOS
        {
            class MyRenderer : FrameRenderer
            {
    
                protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
                {
                    base.OnElementChanged(e);
    
    
                    var frame = (MyFrame)Element;
                    if (frame == null)
                        return;
    
    
    
                    if (frame.HasShadow)
                    {
                        this.Layer.ShadowColor = frame.ShadowColor.ToCGColor();
                    }
    
                    if (frame.BorderWidth > 0)
                    {
                        this.Layer.BorderColor = frame.BorderColor.ToCGColor();
                        this.Layer.BorderWidth = frame.BorderWidth;
                    }
    
                }   
            }
        }
    

    Android Renderer

    [assembly: ExportRenderer(typeof(MyFrame), typeof(MyAndroidRenderer))]
    namespace FormApp1.Droid
    {
        public class MyAndroidRenderer: FrameRenderer
        {
    
            Context context;
            public MyAndroidRenderer(Context context):base(context) {
    
                this.context = context;
    
    
            }
    
    
            protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
            {
                base.OnElementChanged(e);
                if (e.NewElement != null)
                {
                    ViewGroup.SetBackgroundResource(Resource.Drawable.shadow);
                }
            }
        }
    }
    

    For more details, you can refer this thread: https://stackoverflow.com/a/42527548/8187800 .

  • lescperlescper Member ✭✭✭✭✭

    @jezh I tried but OnDraw not be called on android.

  • jezhjezh Member, Xamarin Team Xamurai
    Accepted Answer

    In Android platform, we need to create file shadow.xml under Drawable folder of Android resources:

    <?xml version="1.0" encoding="utf-8" ?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <shape android:shape="rectangle">
                <solid android:color="#CABBBBBB" />
                <corners android:radius="2dp" />
            </shape>
        </item>
    
        <item
            android:left="0dp"
            android:right="0dp"
            android:top="0dp"
            android:bottom="2dp">
            <shape android:shape="rectangle">
                <solid android:color="@android:color/white" />
                <corners android:radius="2dp" />
            </shape>
        </item>
    </layer-list>
    

    And in Android Renderer, do like this:

    [assembly: ExportRenderer(typeof(MyFrame), typeof(MyAndroidRenderer))]
    namespace FormApp1.Droid
    {
        public class MyAndroidRenderer: FrameRenderer
        {
    
            Context context;
            public MyAndroidRenderer(Context context):base(context) {
    
                this.context = context;
    
            }
    
            protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
            {
                base.OnElementChanged(e);
                if (e.NewElement != null)
                {
                    ViewGroup.SetBackgroundResource(Resource.Drawable.shadow);
                }
            }
        }
    }
    
  • lescperlescper Member ✭✭✭✭✭

    @jezh I am so sad and I used skiasharp to do it

    So I will not try your code but accept it.

Sign In or Register to comment.