Bug 46924 - iOS: PlatformEffect renders with "old" properties (when changing .IsVisible)
Summary: iOS: PlatformEffect renders with "old" properties (when changing .IsVisible)
Status: CONFIRMED
Alias: None
Product: Forms
Classification: Xamarin
Component: Forms ()
Version: 2.3.4
Hardware: PC Windows
: Normal normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2016-11-14 11:08 UTC by Florian
Modified: 2017-03-27 19:40 UTC (History)
4 users (show)

Tags: platformeffect isvisible ac
Is this bug a regression?: ---
Last known good build:


Attachments
Project to reproduce the bug (187.11 KB, application/x-zip-compressed)
2016-11-14 11:08 UTC, Florian
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report for Bug 46924 on Developer Community or GitHub if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: Developer Community HTML or GitHub Markdown
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:
Status:
CONFIRMED

Description Florian 2016-11-14 11:08:59 UTC
Created attachment 18452 [details]
Project to reproduce the bug

I tried to integrate a PlatformEffect following this great tutorial: http://intellitect.com/native-animation-effects-in-xamarin-forms/

The attached reproduction project is based on that.

The native fade in/out animation which I handle in the PlatformEffect runs fine up to a point where I set .IsVisible to false when fading out is done (for performance reasons) and in a similar manner when fading the view in again I need to set .IsVisible to true at first. As in the tutorial I do the animation on the native "Container" but after the animation I set the target alpha also to the XF element, as well as the .IsVisible to make sure XF and native view "stay in sync". What happens is, when fading in, the element stays invisible until the animation ends and the suddenly becomes visible (without a smooth fade). I've seen different variations on this, depending on the order of setting .IsVisible. I had it at fade out too, where the animation was running fine and at the end, when settings IsVisible to false it becomes fully visible for a frame and after that invisible again.

        private async Task AnimateIn(bool setVisibility)
        {
            var visualElement = Element as VisualElement;

            if ( visualElement != null)
            {
                Container.Alpha = 0f;

                if (!visualElement.IsVisible || setVisibility)
                    Container.Hidden = false;

                visualElement.Opacity = 0f;

                if (!visualElement.IsVisible || setVisibility)
                    visualElement.IsVisible = true;
            }

            await UIView.AnimateNotifyAsync(1,
                () =>
                {
                    Container.Alpha = 1f;
                });

            if (visualElement != null)
            {
                Container.Alpha = 1f;

                visualElement.Opacity = 1f;
            }
        }


        private async Task AnimateOut(bool setVisibility)
        {
            var visualElement = Element as VisualElement;

            await UIView.AnimateNotifyAsync(1,
                () =>
                {
                    Container.Alpha = 0f;
                });

            if (visualElement != null)
            {
                Container.Alpha = 0f;

                if ( setVisibility )
                    Container.Hidden = true;

                visualElement.Opacity = 0f;

                if (setVisibility)
                    visualElement.IsVisible = false;
            }
        }

My guess it that this is dependent on setting IsVisible on the XF element, this somehow seems to trigger a new render but using "old" properties (not the Opacity which has been set immediately before setting IsVisible). This only happens every couple of tries. So I guess the rendering is decoupled from the main thread, most of the the times it works as expected and every 20th time it is wrong. You can reproduce it with the attached project. The "Show Overlay" button will always work (as the IsVisible property is not touched, it just uses the Alpha/Opacity). But "Show Overlay (Set Visibility)" the faulty animation (fade in) happens every 20th try or so. 

I didn't see this error on Android, just on iOS. I use XF 2.3.3-pre4 and the iOS 10.1 emulator.
Comment 1 adrianknight89 2016-11-15 00:38:01 UTC
I think RelativeLayout does not have a Control set. Container is the renderer whereas the visual element is the element, so you're trying to sync two different things. However, I say this without looking at XF source. It might be that Container and visual element are the same things for layouts.

You are setting visual element opacity to 0 in AnimateIn. As the Container alpha animates, your visual is still not visible because of its alpha. So you see the visual only after the animation is completed and visual opacity is set to 1.

Try this:

private async Task AnimateIn()
{
    var visualElement = Element as VisualElement;

    Container.Alpha = 0f;
    Container.Hidden = false;

    visualElement.Opacity = 1f;
    visualElement.IsVisible = true;

    await UIView.AnimateNotifyAsync(1,
    () =>
    {
	Container.Alpha = 1f;
    });
}

I would even remove visualElement altogether. I left it out for demonstration purposes. However, this defeats the purpose of you trying to sync two things together.

This could be further looked at.
Comment 2 Florian 2016-11-16 12:14:45 UTC
The Control is indeed not set. Container is the renderer of the RelativeLayout. 

Please regard, the sudden appearance happens only every 20th (or so) try and it happens after 1s (after the animation is completed), so it stays 0 over the course of the animation and then becomes suddenly 1. Almost as if the animation is not executed at all, besides the 1s which passed by!? I can't make any sense of it, as it works most of the time.

When I edit my sample as you suggested, it always suddenly appears immediately, before or at the start of the animation. 

When I remove any setting of visualElement.Opacity it has the same behaviour (immediately in). I can only guess that somehow setting IsVisible overwrites Opacity with 1 which messes up the animation. But even as in my original code when I set the Opacity to 0 before setting IsVisible it is sometimes (every x-th try) not working => that's what I don't get any sense into.
Comment 3 Paul DiPietro [MSFT] 2017-03-27 19:40:01 UTC
I was able to get this to reproduce with the reproduction project against 2.3.4-pre6 so I'll update this to confirmed until it can get some further investigation.