Skip to content

Shadow on Label disappears permanently and won't come back if Label opacity is ever tweened down to zero #17916

@jonmdev

Description

@jonmdev

Description

This is a bizarre bug I can't explain but is easy to reproduce. If you create a Label with a Shadow, then tween that Label's opacity down to zero in Windows, the Shadow disappears and won't come back.

To illustrate, I created the following simple program which just features a few Labels on screen, and on a Timer, will tween their opacity either from 0 to 1 or 1 to 0 depending on the showHide int which is toggled between +1 (to show) and -1 (to hide):

using System.Diagnostics;

namespace Windows_Shadow_Opacity_Bug {
    public partial class App : Application {
        private double screenWidth;
        private double screenHeight;
        public event Action screenSizeChanged = null;
        double deltaTime = 0;
        int showHide = 1;

        public App() {
            InitializeComponent();

            ContentPage mainPage = new();
            MainPage = mainPage;

            AbsoluteLayout abs = new();
            mainPage.Content = abs;

            VerticalStackLayout vert = new();
            abs.Children.Add(vert);

            //create a group of labels on screen
            List<View> labelList = new();
            for (int i=0; i < 5; i++) {
                Label label = new();
                label.Text = "HELLO MAUI";
                label.FontAttributes = FontAttributes.Bold;
                label.FontSize = 60;
                label.Shadow = new() { Offset =  new Point(0, 5), Radius = 7 };
                vert.Children.Add(label);
                labelList.Add(label);
            }

            
            //animation timer and function
            var timer = Application.Current.Dispatcher.CreateTimer();
            timer.Interval = TimeSpan.FromSeconds( 1 / 180);
            timer.Start();
            DateTime dateTime = DateTime.Now;
            timer.Tick += delegate {
                deltaTime = (DateTime.Now - dateTime).TotalSeconds;
                dateTime = DateTime.Now;

                double animationTime = 1;
                double targetOpacity = (showHide + 1) / 2;

                for (int i = 0; i < labelList.Count; i++) {
                    if (targetOpacity != labelList[i].Opacity) {

                        //tweening the label opacity between 1 and 0 will cause the shadow to be lost:
                        labelList[i].Opacity = Math.Clamp(labelList[i].Opacity + showHide * deltaTime/ animationTime, 0, 1);
                        
                        //alternatively if you immediately change the opacity between zero and one in 1 step back and forth each time click rather than tween, shadow is NOT lost:
                        //labelList[i].Opacity = Math.Clamp(showHide, 0, 1); 
                    }
                }

            };

            //tap function
            TapGestureRecognizer tap = new();
            tap.Tapped += delegate {
                showHide *= -1;
            };

            //border to take clicks
            Border clickBorder = new();
            abs.Children.Add(clickBorder);
            clickBorder.BackgroundColor = Colors.Blue;
            clickBorder.Opacity = 0;
            clickBorder.GestureRecognizers.Add(tap);

            //screen resize function
            mainPage.SizeChanged += delegate {
                if (mainPage.Width > 0 && mainPage.Height > 0) {
                    screenWidth = mainPage.Width;
                    screenHeight = mainPage.Height;
                    vert.WidthRequest = screenWidth;
                    vert.HeightRequest = screenHeight;
                    clickBorder.WidthRequest = screenWidth;
                    clickBorder.HeightRequest = screenHeight;
                    abs.HeightRequest = screenHeight;
                    abs.WidthRequest = screenWidth;

                }

            };


        }
    }
}

This is what it looks like if you play it to start:

windows shadow 1

If you click the screen, these labels will fade out. If you click again, they will fade back in. But now bizarrely their Shadows will be gone:

windows shadow 2

What is even more interesting is if you comment out the line labelList[i].Opacity = Math.Clamp(labelList[i].Opacity + showHide * deltaTime/ animationTime, 0, 1); and let back in the line labelList[i].Opacity = Math.Clamp(showHide, 0, 1); so this no longer tweens the opacity but rather sets it hard back and forth between 0 and 1, the same problem does not happen.

So this problem is only provoked by tweening opacity. And it only happens in Windows.

I presume there must be some intermediate opacity between 0 and 1 that is triggering a glitch and only in Windows but don't know what specific value it is or why it is happening.

Thanks for any help or solutions.

Steps to Reproduce

  1. Create a new project by File > New and name it "Windows Shadow Opacity Bug"
  2. Copy paste the code above to replace App.xaml.cs
  3. Play project and click screen to fade out labels, click again to fade them back in.
  4. Observe that when they return their Shadows are gone

Link to public reproduction project repository

https://github.com/jonmdev/Windows-Shadow-Opacity-Bug

Version with bug

7.0.92

Is this a regression from previous behavior?

No, this is something new

Last version that worked well

Unknown/Other

Affected platforms

Windows

Affected platform versions

Windows 10

Did you find any workaround?

If you never tween Label opacities but only hard set them to 0 or 1, this can be avoided. If you also keep the opacity floor above around 0.01 or 0.05 or so (I believe) it doesn't happen. So I presume there is some math or programming error that is happening once Label opacity gets close to zero but not exactly zero.

Relevant log output

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-drawingShapes, Borders, Shadows, Graphics, BoxView, custom drawingplatform/windowss/triagedIssue has been revieweds/verifiedVerified / Reproducible Issue ready for Engineering Triaget/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions