Rg.Plugins.Popup icon indicating copy to clipboard operation
Rg.Plugins.Popup copied to clipboard

Popup page flickers on appearing

Open lassana opened this issue 3 years ago • 15 comments

🐛 Bug Report

If the popup page has a ListView in its content, and ItemsSource of that ListView gets set in OnSizeAllocated() or OnAppearingAnimationBegin, the appearing animation gets broken and the page flickers: at first the page is shown in the center of the screen for a short moment, and then the actual animation starts. The behavior is pretty much the same as in #404

It can be reproduced with the latest X.F 5.0.0.2196 and Rg.Plugins.Popup 2.0.0.14.

The reproduction sample: RgPopupAppearingBug.zip

    public class BuggedPopup : PopupPage
    {
        private readonly ListView _listView;
        private bool _isInitialized;

        public BuggedPopup()
        {
            CloseWhenBackgroundIsClicked = false;

            Animation = new MoveAnimation
            {
                PositionIn = MoveAnimationOptions.Bottom,
                PositionOut = MoveAnimationOptions.Bottom,
                DurationIn = 400,
                DurationOut = 300,
                EasingIn = Easing.SinOut,
                EasingOut = Easing.SinIn,
                HasBackgroundAnimation = true
            };

            _listView = new ListView(ListViewCachingStrategy.RecycleElementAndDataTemplate)
            {
                BackgroundColor = Color.Transparent,
                HasUnevenRows = true,
                ItemTemplate = new DataTemplate(() =>
                {
                    var label = new Label();
                    label.FontAttributes = FontAttributes.Bold;
                    label.SetBinding(Label.TextProperty, new Binding("."));
                    return new ViewCell
                    {
                        View = label
                    };
                })
            };

            Content = new Frame
            {
                HeightRequest = 300,
                WidthRequest = 500,
                HorizontalOptions = LayoutOptions.Center,
                VerticalOptions = LayoutOptions.Center,
                BorderColor = Color.Red,
                Content = new StackLayout
                {
                    Orientation = StackOrientation.Vertical,
                    Children =
                    {
                        new Button
                        {
                            Text = "Close",
                            Command = new Command(() => this.Navigation.PopPopupAsync())
                        },
                        _listView
                    }
                }
            };
        }

        protected override void OnAppearingAnimationBegin()
        {
            if (!_isInitialized)
            {
                /*
                 * This is the key place.
                 * 
                 * Setting ItemsSource in OnSizeAllocated or OnAppearingAnimationBegin
                 * breaks the appearing animation.
                 */
                _isInitialized = true;
                _listView.ItemsSource = Enumerable.Repeat(
                    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
                    30)
                    .ToList();
            }
            base.OnAppearingAnimationBegin();
        }
    }

https://user-images.githubusercontent.com/2004960/138688360-3120e2f5-fb5b-4203-a683-588dc5d5b21a.mp4

Expected behavior

The page appearing animation is smooth.

Reproduction steps

Open attached project, run, and click "Show Popup".

Configuration

Version: 2.0.0.14

Platform:

  • [x] :iphone: iOS
  • [ ] :robot: Android
  • [ ] :checkered_flag: WPF
  • [ ] :earth_americas: UWP
  • [ ] :apple: MacOS
  • [ ] :tv: tvOS
  • [ ] :monkey: Xamarin.Forms

lassana avatar Oct 25 '21 11:10 lassana

I am also experiencing this issue

brandonward34 avatar Nov 02 '21 05:11 brandonward34

Same here, was also in 2.0.0.13.

Suplanus avatar Nov 04 '21 13:11 Suplanus

Any update on this? we have users reporting this happens quite frequently now... Ive started looking into a little more and seems like it has something to do with this line taskList.Add(content.TranslateTo(_defaultTranslationX, _defaultTranslationY, DurationIn, EasingIn)); seems similar to issue #404

brandonward34 avatar Nov 25 '21 03:11 brandonward34

Same here guys

ShadowOfPhantom avatar Nov 25 '21 16:11 ShadowOfPhantom

Yep, I see this also. Happens on all my popups, not just those with ListViews.

rjhind avatar Dec 06 '21 08:12 rjhind

Has anyone been able to solve this? This happens on every popup for us. Thanks.

rjhind avatar Jan 24 '22 10:01 rjhind

Still happening on 2.1.0 as well, just an FYI

brandonward34 avatar Jan 30 '22 21:01 brandonward34

any workaround?

brunonocetti avatar May 04 '22 20:05 brunonocetti

Any update on a fix for this? I took an approach of overriding the MoveAnimation and adding a Task.Delay to the OnAppearing and it didn't seem to help. Pretty annoying bug that takes away a clean user-experience.

bradencohen avatar Jul 12 '22 00:07 bradencohen

I am having this issue as well. Has anyone migrated to a different nuget due to this issue?

donatellijl avatar Sep 28 '22 15:09 donatellijl

I am having this issue as well. Has anyone migrated to a different nuget due to this issue?

You don't really have to use this plugin, just remove it from your solution and make the same functionality with only xamarin

ShadowOfPhantom avatar Sep 28 '22 15:09 ShadowOfPhantom

I had the same problem here - iOS would flicker not on every popup, but maybe 1 out of every 3 or so. The approach that I took was to extend the animation class we are using to be a custom animation:

public class SystemDialogAnimation: MoveAnimation

The thing you need to change is in the Appearing method, so if you override that and set another task to update opacity, you can avoid the flicker. I think the issue happens where timing can be out of order, so a call to make the page visible happens right before the call to execute the animation, resulting in a couple of frames where the popup is visible in the initial position.

public override Task Appearing(View content, PopupPage page)
{
    var taskList = new List<Task>
    {
        base.Appearing(content, page)
    };

    if (content != null)
    {
        // set initial opacity
        page.Opacity = 0;

        var topOffset = GetTopOffset(content, page);
        var leftOffset = GetLeftOffset(content, page);

        if (PositionIn == MoveAnimationOptions.Top)
        {
            content.TranslationY = -topOffset;
        }
        else if (PositionIn == MoveAnimationOptions.Bottom)
        {
            content.TranslationY = topOffset;
        }
        else if (PositionIn == MoveAnimationOptions.Left)
        {
            content.TranslationX = -leftOffset;
        }
        else if (PositionIn == MoveAnimationOptions.Right)
        {
            content.TranslationX = leftOffset;
        }

        // quickly make the page opaque to cover up the misplaced frames
        taskList.Add(page.FadeTo(100, 1));
        taskList.Add(content.TranslateTo(_defaultTranslationX, _defaultTranslationY, DurationIn, EasingIn));
    }

    ShowPage(page);

    return Task.WhenAll(taskList);
}

I'll create a PR to hopefully get this pulled in, but in the meantime this might be able to get you by.

jlbeard84 avatar Dec 15 '22 18:12 jlbeard84

@jlbeard84 works like a charm, thanks!

bradencohen avatar Dec 22 '22 21:12 bradencohen

@jlbeard84 you're such a bro, I implemented this and it works. It's still required even with v2.1 NuGet package.

derekvantonder avatar Aug 04 '23 03:08 derekvantonder

@jlbeard84 thank u

tataroch-ka avatar Apr 06 '24 17:04 tataroch-ka