美文网首页
masonry 使用笔记--续

masonry 使用笔记--续

作者: 朽木自雕也 | 来源:发表于2019-01-26 23:58 被阅读5次

    上一篇做完了masonry 的基础用法笔记,现在想要更深入一些了解 masonry 对动画框架的支持,再进一步了解 masonry 的实现原理

    masonry 动画

    准备知识

    在开始演示动画之前得先搞懂几个知识点,要不然就算你能写代码出来实现动画,但是也不会清楚为什么代码要这样写,原理是什么。

    1. UIView 中的 setNeedsLayout 方法,想更深入了解请看官文 setNeedsLayout

    如果要调整视图子视图的布局,请在应用程序的主线程上调用此方法。 此方法记录请求并立即返回。 由于此方法不强制立即更新,而是等待下一个更新周期,因此可以在更新任何视图之前使用它来使多个视图的布局无效。 此行为允许您将所有布局更新合并到一个更新周期,这通常会提高性能。

    // Allows you to perform layout before the drawing cycle happens. -layoutIfNeeded forces layout early
    - (void)setNeedsLayout;
    
    1. UIView 中的 layoutIfNeeded 方法,同样想深入了解可以去看官文 layoutIfNeeded

    使用此方法强制视图立即更新其布局。 使用“自动布局”时,布局引擎会根据需要更新视图的位置,以满足约束的更改。 使用以根视图接收消息的视图,此方法从根开始布局视图子树。 如果没有待处理的布局更新,则此方法退出而不修改布局或调用任何与布局相关的回调。

    - (void)layoutIfNeeded;
    
    1. UIView 中的 layoutSubviews 方法, 官文的描述
      layoutSubviews,有兴趣可以去看看。

    此方法的默认实现在iOS 5.1及更早版本中不执行任何操作。 否则,默认实现使用您设置的任何约束来确定任何子视图的大小和位置。
    子类可以根据需要覆盖此方法,以执行其子视图的更精确布局。 仅当子视图的自动调整大小和基于约束的行为不提供所需的行为时,才应覆盖此方法。 您可以使用实现直接设置子视图的框架矩形。另外,您不应该直接调用此方法。 如果要强制进行布局更新,请在下次绘图更新之前调用setNeedsLayout方法。 如果要立即更新视图的布局,请调用layoutIfNeeded方法。

    - (void)layoutSubviews;    // override point. called by layoutIfNeeded automatically. As of iOS 6.0, when constraints-based layout is used the base implementation applies the constraints-based layout, otherwise it does nothing.
    

    如果相对上面有更加几个方法有更加深入的认识,就得去了解runloop了,可以拜读一下这篇博客:深入理解runloop 堪称神作

    动画效果如下

    Jan-26-2019 21-48-36.gif

    实现代码

    1. 第一步,创建一个 View 来展示动画;创建一个 Button 来触发动画;
    - (void)createDemo {
        self.animationView = [[UIView alloc] init];
        self.animationView.backgroundColor = UIColor.greenColor;
        //1
        [self.view addSubview:self.animationView];
        [self.animationView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerX.mas_equalTo(self.view.mas_centerX);
            make.centerY.mas_equalTo(self.view.mas_centerY);
            make.width.height.mas_equalTo(100);
        }];
        
        UIButton *button = [[UIButton alloc]init];
        button.backgroundColor = UIColor.redColor;
        [button setTitle:@"放大" forState:UIControlStateNormal];
        [button setTitle:@"缩小" forState:UIControlStateSelected];
        [button addTarget:self action:@selector(clicked:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:button];
        
        [button mas_makeConstraints:^(MASConstraintMaker *make) {
            make.bottom.mas_equalTo(-100);
            make.centerX.mas_equalTo(self.view.mas_centerX);
            make.height.width.mas_equalTo(100);
        }];
    }
    
    1. 第二步,实现 Button 的点击事件
    - (void)clicked:(UIButton *)btn {
        btn.selected = !btn.selected;
        //2
        [self.animationView setNeedsLayout];
        if (btn.selected) {
            [UIView animateWithDuration:0.25 animations:^{
                [self.animationView mas_updateConstraints:^(MASConstraintMaker *make) {
                    make.width.height.mas_equalTo(300);
                }];
                //3
                [self.animationView layoutIfNeeded];
            }];
        } else {
            [UIView animateWithDuration:0.25 animations:^{
                [self.animationView mas_updateConstraints:^(MASConstraintMaker *make) {
                    make.width.height.mas_equalTo(100);
                }];
                //3
                [self.animationView layoutIfNeeded];
            }];
            
        }
    }
    

    当 masonry 执行布局代码是并不会立马进行布局,在 setNeedsLayout 时不会立即更新布局,同时还会使后面执行的视图布局无效,而调用 layoutIfNeeded 会强制立即更新布局。这里有点难理解,但是我找不出更合适的解释,表示很对不住语文老师。

    masonry 源码解读博客再配合源码测试,深入理解 masonry 杠杠的

    相关文章

      网友评论

          本文标题:masonry 使用笔记--续

          本文链接:https://www.haomeiwen.com/subject/azjwjqtx.html