locked
IsVisible inside Control inside StackLayout inside ScrollView not work? RRS feed

  • Question

  • User99695 posted

    Hello! I use this scheme of form like this:

    Content= new ScrollView { HorizontalOptions=LayoutOptions.Fill, VerticalOptions=LayoutOptions.Fill, Content= new StackLayout { HorizontalOptions=LayoutOptions.FillAndExpand, VerticalOptions=LayoutOptions.FillAndExpand, Childrent= { Control1 { IsVisible=false}, Control2 { IsVisible=false}, Control3 { IsVisible=false}, Control4 { IsVisible=false}, Control5 { IsVisible=false}, Control6 { IsVisible=false}, Control7 { IsVisible=false}, } } };

    When need, i change "IsVisible" property of controls from "false" to "true". And some time (not every time!) some controls not appear! I see empty space in stack layout, but not controls. It seems like this:

    " label1 label2 label3

    label5

    label7 "

    Some time not appear any of control, some time - appear all of them. Does anyone know why this is happening?

    Tuesday, March 10, 2015 5:48 AM

Answers

  • User120194 posted

    After lots of time wasted on this egregious bug, I found a workaround for my scenario.

    For child controls of StackLayout, set HeightRequest = 0 instead of IsVisible = false, and HeightRequest = -1 instead of IsVisible = true.

    For example, I have a StackLayout that contains "sections" of a form, where each section is StackLayout.

    StackLayout _section1, _section2;
    
    var layout = new StackLayout()
    {
        Children = { _section1, _section2 },
    }
    
    SetVisibility(_section2, false);
    
    private void SetSectionVisibility(StackLayout section, bool isVisible)
    {
        #if __IOS__
        // HACK: IsVisible does not work reliably on iOS
        // See https://bugzilla.xamarin.com/show_bug.cgi?id=29086
        section.HeightRequest = isVisible ? -1d : 0;
        #else
        section.IsVisible = visible;
        #endif
    }
    

    I use SetSectionVisibility instead of IsVisible to show or hide each section.

    It's better than the Opacity workaround, because the sections expand or collapse as you would expect when setting IsVisible, and the controls don't get focus when using the tab button, either.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, May 12, 2015 11:50 PM
  • User99695 posted

    Now we use this workaround:

    public class Batch
    {
        private readonly ILayoutController visualElement;
    
        public Batch(ILayoutController visualElement)
        {
            this.visualElement = visualElement;
        }
    
        public IDisposable Begin()
        {
            var animatables = GatherAnimatables(visualElement).ToArray();
            foreach (var animatable in animatables)
                animatable.BatchBegin();
    
            return new ActionDisposable(() =>
                                        {
                                            foreach (var animatable in animatables)
                                                animatable.BatchCommit();
                                        });
        }
    
        private static IEnumerable<IAnimatable> GatherAnimatables(ILayoutController root)
        {
            return root.Children.OfType<IAnimatable>()
                       .Concat(root.Children.OfType<ILayoutController>().SelectMany(GatherAnimatables));
        }
    }
    

    And using batch in every change of components properties. Horrible, but work.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Monday, June 22, 2015 7:57 AM

All replies

  • User53467 posted

    I am also facing this same issue with the same scenario (Only in iOS) after updating into Xamarin Forms 1.4.0 but it was working fine with XF 1.3.3. Any idea about this issue?

    Tuesday, March 10, 2015 10:29 AM
  • User99695 posted

    CloudCherry i return to 1.3.3.6323 - and it work! Thank you! Problem in this part: when you set IsVisible=true some time "Hidden" value of native control some time not setted to false (or i can see in debug - it setted, but in one moment changed back to wrong value).

    In last version (Xamarin.Forms 1.4.1.6342-pre1) promlem not fixed.

    Tuesday, March 10, 2015 12:54 PM
  • User61711 posted

    Waiting for xamarin guys response to look into it in and make it workable in current version. This issue is only on iOS platform, works as expected on android. I am facing issue while testing with iPad mini, OS: iOS 8.1

    Wednesday, March 11, 2015 10:06 AM
  • User113929 posted

    Same here. Any idea what's causing this bug?

    Thursday, March 12, 2015 9:01 AM
  • User20002 posted

    I am having the same exact problem. Xamarin please help!

    Many are facing this problem.

    Monday, April 13, 2015 12:49 PM
  • User58997 posted

    I am having a similar problem without the scrollview Buttons in a stacklayout does not always layout when toggling visibility : http://forums.xamarin.com/discussion/37917/bug-switching-isvisible-on-a-button-does-not-redraw-the-button#latest

    Tuesday, April 14, 2015 3:46 PM
  • User95096 posted

    I have the same issue with my application. In android works well but in iOS, for Xamarin.Forms:

    • version > 1.3.3.6323 it doesn't work
    • version = 1.3.3.6323 the first time I change the visility it doesn't work but following changes works well.
    • version = 1.3.1.6296 works perfectly. I downgraded my solution to this version waiting for a fix.

    In latest versions, if the mobile screen rotates, the elements appear

    Wednesday, April 15, 2015 10:06 AM
  • User120194 posted

    After lots of time wasted on this egregious bug, I found a workaround for my scenario.

    For child controls of StackLayout, set HeightRequest = 0 instead of IsVisible = false, and HeightRequest = -1 instead of IsVisible = true.

    For example, I have a StackLayout that contains "sections" of a form, where each section is StackLayout.

    StackLayout _section1, _section2;
    
    var layout = new StackLayout()
    {
        Children = { _section1, _section2 },
    }
    
    SetVisibility(_section2, false);
    
    private void SetSectionVisibility(StackLayout section, bool isVisible)
    {
        #if __IOS__
        // HACK: IsVisible does not work reliably on iOS
        // See https://bugzilla.xamarin.com/show_bug.cgi?id=29086
        section.HeightRequest = isVisible ? -1d : 0;
        #else
        section.IsVisible = visible;
        #endif
    }
    

    I use SetSectionVisibility instead of IsVisible to show or hide each section.

    It's better than the Opacity workaround, because the sections expand or collapse as you would expect when setting IsVisible, and the controls don't get focus when using the tab button, either.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, May 12, 2015 11:50 PM
  • User120194 posted

    I thought this problem had magically fixed itself in some cases, but then it showed up in release builds again.

    After more investigation, it turns out that using the "Link all assemblies" option was breaking it. Turn it off, and things start showing and hiding properly again.

    Just another thing to check should you run into this problem.

    Wednesday, May 27, 2015 5:48 PM
  • User129256 posted

    I've been having this problem for a couple weeks now. My problem was I had 4 elements with IsVisible bindings to the same boolean. generally the two labels would appear/disappear properly but the two entries had trouble appearing. I had been putting off fixing it as it is such a strange iOS specific bug. A simple workaround I just tried was to put all four elements in a basic stacklayout and put the binding on the stacklayout instead of the 4 views.

    It seems to be working fine so far... If this doesn't work, I'll try the heightrequest method.

    Friday, June 12, 2015 8:28 PM
  • User99695 posted

    Now we use this workaround:

    public class Batch
    {
        private readonly ILayoutController visualElement;
    
        public Batch(ILayoutController visualElement)
        {
            this.visualElement = visualElement;
        }
    
        public IDisposable Begin()
        {
            var animatables = GatherAnimatables(visualElement).ToArray();
            foreach (var animatable in animatables)
                animatable.BatchBegin();
    
            return new ActionDisposable(() =>
                                        {
                                            foreach (var animatable in animatables)
                                                animatable.BatchCommit();
                                        });
        }
    
        private static IEnumerable<IAnimatable> GatherAnimatables(ILayoutController root)
        {
            return root.Children.OfType<IAnimatable>()
                       .Concat(root.Children.OfType<ILayoutController>().SelectMany(GatherAnimatables));
        }
    }
    

    And using batch in every change of components properties. Horrible, but work.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Monday, June 22, 2015 7:57 AM
  • User132171 posted

    Anyone know if this ever was supposed to have been fixed? I'm having the issue with 2.x on Android now. It's really annoying having stacklayouts randomly decide to draw properly when a child's IsVisible changes.

    Tuesday, February 9, 2016 12:12 AM
  • User147638 posted

    I'm getting this too on Android, using Forms 2.0.1.6495. ScrollView seems to be the culprit. Just about to experiment with the HeightRequest hack.

    Wednesday, February 17, 2016 9:54 AM
  • User6040 posted

    @DmitryMoiseev can u share an example on how to use the batch trick?

    Wednesday, March 9, 2016 2:28 PM
  • User6040 posted

    @DmitryMoiseev can u share ActionDisposable class implementation?

    Wednesday, March 9, 2016 2:40 PM
  • User6040 posted

    @DmitryMoiseev it looks like this?

    ``` public class ActionDisposable : IDisposable { public ActionDisposable(Action batchCommit) { }

        #region IDisposable implementation
        public void Dispose ()
        {
        }
        #endregion
    }
    

    ```

    If yes, i only need and example on how to use Batch

    Wednesday, March 9, 2016 2:48 PM
  • User99695 posted
    public interface IBatch
    {
        IDisposable Begin();
    }
    
    public class Batch: IBatch
    {
        public static readonly IBatch Empty = new EmptyBatch();
    
        private readonly ILayoutController visualElement;
    
        public Batch(ILayoutController visualElement)
        {
            this.visualElement = visualElement;
        }
    
        public IDisposable Begin()
        {
            var animatables = GatherAnimatables(visualElement).ToArray();
            foreach (var animatable in animatables)
                animatable.BatchBegin();
    
            return new ActionDisposable(() =>
                                        {
                                            foreach (var animatable in animatables)
                                                animatable.BatchCommit();
                                        });
        }
    
        private class EmptyBatch : IBatch
        {
            public IDisposable Begin()
            {
                return new ActionDisposable(() => {});
            }
        }
    
        private static IEnumerable<IAnimatable> GatherAnimatables(ILayoutController root)
        {
            return root.Children.OfType<IAnimatable>()
                       .Concat(root.Children.OfType<ILayoutController>().SelectMany(GatherAnimatables));
        }
    }
    
    Thursday, March 10, 2016 4:43 AM
  • User99695 posted

    After last update this does not help to. IsVisible broken again. In production. Catastrofic quality...

    Friday, September 23, 2016 12:04 PM
  • User369943 posted

    any update on this? as @DmitryMoiseev said, it is broken again. any new workaround for this? I've tried the one listed above, not working anymore.

    Tuesday, June 19, 2018 10:27 AM
  • User22401 posted

    I was seeing something similar to this with a custom control I wrote. When I set it to IsVisible="false" it would no properly disappear. In my case the problem was that I forgot to call base.OnPropertyChanged(...) in my override.

    Tuesday, March 17, 2020 9:27 AM