locked
Frame doesn't have shadow effect below API Level 28 Android RRS feed

  • Question

  • User391726 posted

    I've created a custom renderer for Frame to feel like CardView in Android it works fine on Android P but i've tested on API 21,22,23 it doesn't have any kind of effect. Here is my Android Renderer.

    ``` public class ShadowFrameRenderer : Xamarin.Forms.Platform.Android.AppCompat.FrameRenderer { public ShadowFrameRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs e) { base.OnElementChanged(e); if (e.NewElement != null && e.NewElement is ShadowFrame) { Elevation = 30.0f; TranslationZ = 0.0f; SetZ(30f); //this.SetBackgroundResource(Resource.Drawable.shadow); //GradientDrawable drawable = (GradientDrawable)this.Background; //drawable.SetColor(Android.Graphics.Color.ParseColor("#F0F0F0")); } UpdateElevation(); }

        private void UpdateElevation()
        {
            //var materialFrame = (ShadowFrame)Element;
    
            // we need to reset the StateListAnimator to override the setting of Elevation on touch down and release.
            if(Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)
            Control.StateListAnimator = new Android.Animation.StateListAnimator();
    
            // set the elevation manually
    
                ViewCompat.SetElevation(this, 10);
                ViewCompat.SetElevation(Control, 10);
            if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)
            {
                Control.Elevation = 10;
                Control.CardElevation = 10;
            }
    
        }
    
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            UpdateElevation();
            //if (e.PropertyName == "Elevation")
            //{
            //    UpdateElevation();
            //}
            }
    

    ```

    Friday, July 10, 2020 7:33 AM

Answers

  • User382871 posted

    Try to set the OutlineColor to White for the custom frame. I've test the code, it works on the api 23. <ContentPage.Content> <controls:ShadowFrame Padding="10" Margin="10" OutlineColor="White"> ... </controls:ShadowFrame> </ContentPage.Content>

    Refer to: https://forums.xamarin.com/discussion/comment/335625/#Comment_335625

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Monday, July 13, 2020 9:11 AM

All replies

  • User382871 posted

    I tested the posted code in a sample, it works fine on the android 8 device. But the effect is not obvious, try to increase the elevation value to check that.
    private void UpdateElevation() { ... if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop) { Control.Elevation = 20; Control.CardElevation = 20; } } You could also use the following code to achieve the functin. ``` public class CustomFrameRenderer : Xamarin.Forms.Platform.Android.AppCompat.FrameRenderer { public CustomFrameRenderer(Context context) : base(context) { }

    protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
    {
        base.OnElementChanged(e);
        if (e.NewElement != null)
        {
            Control.SetElevation(60);
            Control.TranslationZ = 10;
        }
    }
    

    } ```

    Friday, July 10, 2020 9:41 AM
  • User391726 posted

    @Jarvan said: I tested the posted code in a sample, it works fine on the android 8 device. But the effect is not obvious, try to increase the elevation value to check that.
    private void UpdateElevation() { ... if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop) { Control.Elevation = 20; Control.CardElevation = 20; } } You could also use the following code to achieve the functin. ``` public class CustomFrameRenderer : Xamarin.Forms.Platform.Android.AppCompat.FrameRenderer { public CustomFrameRenderer(Context context) : base(context) { }

    protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
    {
        base.OnElementChanged(e);
        if (e.NewElement != null)
        {
            Control.SetElevation(60);
            Control.TranslationZ = 10;
        }
    }
    

    } ```

    Dear @Jarvan Thanks for your kind suggestion but unfortunately that doesn't work. I've tested on API 23.

    Friday, July 10, 2020 10:52 AM
  • User391726 posted

    Dear @Jarvan Here is XAML of the layout

    ```

                    <Grid ColumnSpacing="0" VerticalOptions="FillAndExpand">
                <StackLayout BackgroundColor="{DynamicResource PMedium}"
                                     x:Name="ListingLayoutB" VerticalOptions="FillAndExpand">
                    <Label Text="LISTING" HorizontalOptions="CenterAndExpand" TextColor="White" x:Name="ListingTxt"
                               FontSize="15" FontFamily="{StaticResource SBold}" VerticalOptions="CenterAndExpand"/>
                </StackLayout>
    
                <StackLayout Grid.Column="1" BackgroundColor="White"  x:Name="DealsLayoutB" VerticalOptions="FillAndExpand">
                    <Label Text="DEALS" HorizontalOptions="CenterAndExpand" TextColor="{DynamicResource PMedium}" x:Name="DealsTxt"
                               FontSize="15" VerticalOptions="CenterAndExpand" FontFamily="{StaticResource SBold}"/>
                </StackLayout>
    
            </Grid>
                      </Grid>
            </controls:ShadowFrame>
    </ContentPage.Content>
    

    ```

    Here is the Result.

    Friday, July 10, 2020 12:29 PM
  • User382871 posted

    I've tested the code on api 23, the frame doesn't work. The function code may not be suitable for the low API the low api. To avoid this issue, you could add the shadow effect by setting background for the 'frame' view. ``` public class CustomFrameRenderer : FrameRenderer { public CustomFrameRenderer(Context context) : base(context) { }

    protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
    {
        base.OnElementChanged(e);
        if (e.NewElement != null && e.NewElement is CustomFrame)
        {
            ViewGroup.SetBackgroundResource(Resource.Drawable.shadow);
        }
    }
    

    } shadow.xml

    ```

    Refer to: https://stackoverflow.com/questions/42505696/xamarin-forms-shadow-on-frame-in-android

    Friday, July 10, 2020 1:30 PM
  • User391726 posted

    Dear @Jarvan Thanks again for your cooperation but this drawable is just showing a bottom gray line. It doesn't feels like shadow.

    Friday, July 10, 2020 2:27 PM
  • User391726 posted

    Dear @LandLu. Do you have any suggestion?

    Friday, July 10, 2020 2:29 PM
  • User382871 posted

    Try to set the OutlineColor to White for the custom frame. I've test the code, it works on the api 23. <ContentPage.Content> <controls:ShadowFrame Padding="10" Margin="10" OutlineColor="White"> ... </controls:ShadowFrame> </ContentPage.Content>

    Refer to: https://forums.xamarin.com/discussion/comment/335625/#Comment_335625

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Monday, July 13, 2020 9:11 AM
  • User391726 posted

    @Jarvan said: Try to set the OutlineColor to White for the custom frame. I've test the code, it works on the api 23. <ContentPage.Content> <controls:ShadowFrame Padding="10" Margin="10" OutlineColor="White"> ... </controls:ShadowFrame> </ContentPage.Content>

    Refer to: https://forums.xamarin.com/discussion/comment/335625/#Comment_335625

    Thank you so much dear @Jarvan . strange but it's working.

    Monday, July 13, 2020 3:20 PM