GithubHelp home page GithubHelp logo

Comments (10)

lluisgerard avatar lluisgerard commented on May 20, 2024

Ok, noticed that first rows were pretty low to see the animation on first run. I inverted the numbers so rows can go from 100% to 0%.

from masonry.

cloudkite avatar cloudkite commented on May 20, 2024

@lluisgerard thanks for the very detailed issue info!

I think adding [self setNeedsLayout] before the animation block should fix your issue.
Because you are changing a subview constraint the superview does not realise it needs laying out until the next runloop which will be after the animation block.

Let me know if that helps

from masonry.

lluisgerard avatar lluisgerard commented on May 20, 2024

Thanks @cloudkite, I will post a GIF here showing both cases because is hard to explain in words.

With [self setNeedsLayout] seems that the animation blocks triggers in the middle of the layout and the whole view grows from top to bottom (not horizontally).

Dispatch After VS [self setNeedsLayout]
dispatch_after setneedslayout_

from masonry.

lluisgerard avatar lluisgerard commented on May 20, 2024

In fact, when you set the percentage the first thing the code does is [self layoutIfNeeded] after equalTo(@0). This is key or the frame.size will be zero the first time you run the app:

    self.animateConstraint.equalTo(@0);
    [self layoutIfNeeded];

Using setNeedsLayout here doesn't work and you never see the bar growing from 0 but the last percentage (because is reusing each cell).

According to documentation:
layoutIfNeeded:
Use this method to force the layout of subviews before drawing. Starting with the receiver, this method traverses upward through the view hierarchy as long as superviews require layout. Then it lays out the entire tree beneath that ancestor. Therefore, calling this method can potentially force the layout of your entire view hierarchy.

setNeedsLayout:
Call this method on your application’s main thread when you want to adjust the layout of a view’s subviews. This method makes a note of the request and returns immediately. Because this method does not force an immediate update, but instead waits for the next update cycle, you can use it to invalidate the layout of multiple views before any of those views are updated. This behavior allows you to consolidate all of your layout updates to one update cycle, which is usually better for performance.

I will continue searching for more information about this to find an elegant way, will post something asap, thanks.

from masonry.

lluisgerard avatar lluisgerard commented on May 20, 2024

Ok, here is what I found:

  • The main problem is that the cell width is still growing while the first child animation triggers.

With this in mind, I removed the dispatch_after workaround and used [self setNeedsLayout] as @cloudkite suggested #40 (comment).

What I did then is call [self layoutIfNeeded] in the cell before setting the bar percentage:
Cell's method:

- (void)setPercentage:(float)percentage {
    _percentage = percentage;
    [self layoutIfNeeded]; // NEW!
    [self.animatedView setPercentage:_percentage];
}

Result:
cell1

  • Here you can see that the black background covers the whole width and height, so the animatedView is set before the animation 👍
  • The green view still grows/animates in height but is not so annoying as before.

⚠️ Now I have another issue with the numberLabel that doesn't grows with the bar the first load. Everything works fine when reusing the cell.

    [self.numberLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.viewThatGrows);
        make.left.equalTo(self.viewThatGrows).offset(5).priorityHigh();
        make.right.equalTo(self.viewThatGrows).offset(-5).priorityLow();
        make.bottom.equalTo(self.viewThatGrows);
    }];

⚠️ Guess I will have to tweak a little bit this label to make it never disappear on the left but stick to the right as the bar grows to make it work on first and reuse loads. It works well when I just set the the right constraint (but obviously it disappear if the bar is too small).

(man, this thread is getting large, sorry 🐙)

from masonry.

cloudkite avatar cloudkite commented on May 20, 2024

@lluisgerard I think you having problems as setting percentage could happen before the cell has a frame. Try the following:

in LLGCell.m

- (void)layoutSubviews {
    [super layoutSubviews];
    [self.animatedView setPercentage:_percentage];
}

- (void)setPercentage:(float)percentage {
    _percentage = percentage;
    [self setNeedsLayout];
}

in LLGAnimatedView.m

- (void)setPercentage:(float)percentage {
    _percentage = percentage;

    self.numberLabel.text = [NSString stringWithFormat:@"%i%%", (int)_percentage];

    self.animateConstraint.equalTo(@0);
    [self layoutIfNeeded];

    float width = CGRectGetWidth(self.frame) * (_percentage / 100.0);
    self.animateConstraint.equalTo(@(width));
    [UIView animateWithDuration:1.0f
                          delay:0.0f
         usingSpringWithDamping:0.4f
          initialSpringVelocity:0.9f
                        options:UIViewAnimationOptionCurveEaseInOut
                     animations:^{
                         [self layoutIfNeeded];
                     } completion:nil];
}

from masonry.

cloudkite avatar cloudkite commented on May 20, 2024

I tested it with above code, seems fix the issues as far as I can tell.

BTW what are you using for creating gifs?

from masonry.

lluisgerard avatar lluisgerard commented on May 20, 2024

Amazing! that's what I was missing the whole time! layoutSubviews 👍 thanks!!!!

Gifrocket: http://www.gifrocket.com Is the first time I use it but works very well. I think you can record the video with QuickTime but I'm using a payed app iShowU.

from masonry.

lluisgerard avatar lluisgerard commented on May 20, 2024

Just pushed these new changes to the example. 🎉 ✌️

from masonry.

lluisgerard avatar lluisgerard commented on May 20, 2024

I removed the layoutSubviews method from the cell to use it in the same animatedView 👍
When iOS calls layoutSubviews everything is already set on the parents views. I think is better to have the animation related stuff on the same place (animatedView), I'm glad it works also 💃

from masonry.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.