• 动画特效三:搜索动画


    本节我们看看搜索动画,也就是点击所搜框。上面的导航或者标题栏会被“顶”上去。先看看效果图。

    业务描写叙述:

    1. 点击搜索框。上面的标题栏会被“顶”上去。同一时候会显示遮罩效果。

    2. 然后你点击遮罩层或者“Cancel”button。标题栏又被弹回来。




    大家或许会感觉到奇怪。这个动画效果,用UIView的block动画,实现起来并不困难。但这并非本节讲述的重要。

    我这里的UI布局。是基于autolayout的;所以这里的动画是对约束的操作。并非对frame的操作。基于此动画,我也会延伸解说一下autolayout实现的基本原理。

    一、UI布局。


    上面的UI元素全都是使用autolayout布局。而本节中的动画效果事实上就是针对NavView运行的动画。它的约束列表例如以下:


    观察动画效果:我们能够发现。此动画事实上就是将NavView推出父View而且推动的距离就是NavView自己的高度。所以我们能够连线 "Top Space to: Superview"这个约束,然后对其进行动画操作。约束连线代码例如以下:

    @property (weak, nonatomic) IBOutlet NSLayoutConstraint *navTop;

    二、动画效果分析。

    1. 先看看SearchBar部分的动画效果(注意到SearchBar获取焦点后。"Cancel" button文字颜色变了,而且边框有了颜色)

    边框颜色事实上非常easy。就是来回切换SearchBar的背景图片。

    而“Cancel”button文字颜色则有点复杂,UISearchBar的文字颜色。你通过设置color等相关属性是不起作用的。事实上它本身属于UIBarButtonItem范畴,所以我们能够通过改变appearance来达到目的。并且初始化的代码仅仅须要运行一次。所以能够将代码放在initialize方法中,代码例如以下:

    + (void)initialize {
        UIBarButtonItem *item = [UIBarButtonItem appearance];
        
        NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
        attrs[NSForegroundColorAttributeName] = [UIColor colorWithRed:77/255.0 green:179/255.0 blue:179/255.0 alpha:1];
        [item setTitleTextAttributes:attrs forState:UIControlStateNormal];
        
        NSMutableDictionary *attrsDisabled = [NSMutableDictionary dictionary];
        attrsDisabled[NSForegroundColorAttributeName] = [UIColor grayColor];
        [item setTitleTextAttributes:attrsDisabled forState:UIControlStateDisabled];
    }

    2. 标题栏往上“顶”的动画效果。

    即应该实现SearchBar的代理方法,完毕动画。

    -(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
        //[searchBar becomeFirstResponder];
        // 边框颜色
        searchBar.backgroundImage= [UIImage imageNamed:@"bg_login_textfield_hl"];
        // cancel 文字(它事实上是UIBarButtonItem,所以要显示它,必须进行相印的设置(如字体颜色),在 + (void)initialize方法中)
        [searchBar setShowsCancelButton:YES animated:YES];
        
        self.navTop.constant = -62;
        [UIView animateWithDuration:0.25 animations:^{
            // 运行约束动画
            [self.view layoutIfNeeded];
            self.cover.alpha = 0.4;
        }];
    }

    观察约束动画与frame动画的不同点(frame动画是将终于动画结束的值放在UIView的block代码中,而约束动画是将约束终于改变的值事先赋值好。然后再运行动画)。

    三、iOS中自己主动布局流程及相关方法

    注意到:上面强制运行动画的代码是[self.view layoutIfNeeded].以下我就相关的几个方法及autolayout自己主动布局过程进行说明。

    1、layoutSubviews
    在iOS5.1和之前的版本号,此方法的缺省实现不会做不论什么事情(实现为空),iOS5.1之后(iOS6開始)的版本号,此方法的缺省实现是使用你设置在此view上面的constraints(Autolayout)去决定subviews的position和size。

    UIView的子类假设须要对其subviews进行更精确的布局,则能够重写此方法。仅仅有在autoresizing和constraint-based behaviors of subviews不能提供我们想要的布局结果的时候,我们才应该重写此方法。

    能够在此方法中直接设置subviews的frame。

    我们不应该直接调用此方法。而应当用以下两个方法。而关于layoutSubviews的使用,我在UICollectionView具体解释五:瀑布流中也介绍过。能够实现横屏与竖屏的切换来到达在不同情况下,显示的瀑布流的列数不一致。

    2、setNeedsLayout
    此方法会将view当前的layout设置为无效的,并在下一个upadte cycle里去触发layout更新。

    3、layoutIfNeeded
    使用此方法强制马上进行layout,从当前view開始,此方法会遍历整个view层次(包含superviews)请求layout。因此,调用此方法会强制整个view层次布局。



    基于约束的的方法:
    1、setNeedsUpdateConstraints
    当一个自己定义view的某个属性发生改变,而且可能影响到constraint时,须要调用此方法去标记constraints须要在未来的某个点更新,系统然后调用updateConstraints.

    2、needsUpdateConstraints
    constraint-based layout system使用此返回值去决定是否须要调用updateConstraints作为正常布局过程的一部分。

    3、updateConstraintsIfNeeded
    马上触发约束更新,自己主动更新布局。

    4、updateConstraints
    自己定义view应该重写此方法在当中建立constraints. 注意:要在实如今最后调用[super updateConstraints]
    Auto Layout Process 自己主动布局过程与使用springs and struts(autoresizingMask)比較,Auto layout在view显示之前,多引入了两个步骤:updating constraints 和laying out views。每个步骤都依赖于上一个。display依赖layout。而layout依赖updating constraints。

    updating constraints->layout->display


    第一步:updating constraints,被称为測量阶段。其从下向上(from subview to super view),为下一步layout准备信息。能够通过调用方法setNeedUpdateConstraints去触发此步。constraints的改变也会自己主动的触发此步。

    可是,当你自己定义view的时候,假设一些改变可能会影响到布局的时候。通常须要自己去通知Auto layout,updateConstraintsIfNeeded。

    自己定义view的话,通常能够重写updateConstraints方法,在当中能够加入view须要的局部的constraints。


    第二步:layout,其从上向下(from super view to subview)。此步主要应用上一步的信息去设置view的center和bounds。能够通过调用setNeedsLayout去触发此步骤,此方法不会马上应用layout。假设想要系统马上的更新layout,能够调用layoutIfNeeded。另外,自己定义view能够重写方法layoutSubViews来在layout的project中得到很多其它的定制化效果。


    第三步:display,此步时把view渲染到屏幕上,它与你是否使用Auto layout无关,其操作是从上向下(from super view to subview),通过调用setNeedsDisplay触发。由于每一步都依赖前一步,因此一个display可能会触发layout,当有不论什么layout没有被处理的时候,同理,layout可能会触发updating constraints。当constraint system更新改变的时候。


    须要注意的是,这三步不是单向的。constraint-based layout是一个迭代的过程,layout过程中。可能去改变constraints。有一次触发updating constraints。进行一轮layout过程。


    注意:假设你每一次调用自己定义layoutSubviews都会导致还有一个布局传递,那么你将会陷入一个无限循环中。 
    例如以下图:


  • 相关阅读:
    jQuery 动画之 添加商品到购物车
    <% %> 、 <%= %> 、<%# %> 的区别
    WebFrom模拟MVC
    MVC 基础
    LinQ to SQL 存储过程
    Leetcode练习(Python):数组类:第26题:给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
    Leetcode练习(Python):数组类:第18题:给定一个包含&#160;n 个整数的数组&#160;nums&#160;和一个目标值&#160;target,判断&#160;nums&#160;中是否存在四个元素 a,b,c&#160;和 d&#160;,
    Leetcode练习(Python):数组类:第16题:给定一个包括&#160;n 个整数的数组&#160;nums&#160;和 一个目标值&#160;target。找出&#160;nums&#160;中的三个整数,使得它们的和与&#160;target&#160;最接近。返回这三个数的和。假定每组输入只存在唯一答案。
    Leetcode练习(Python):数组类:第15题:给你一个包含 n 个整数的数组&#160;nums,判断&#160;nums&#160;中是否存在三个元素 a,b,c ,使得&#160;a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。 注意:答案中不可以包含重复的三元组。
    Leetcode练习(Python):数组类:第11题:给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点&#160;(i,&#160;ai) 。在坐标内画 n 条垂直线,垂直线 i&#160;的两个端点分别为&#160;(i,&#160;ai) 和 (i, 0)。找出其中的两条线,使得它们与&#160;x&#160;轴共同构成的容器可以容纳最多的水。
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/7061305.html
Copyright © 2020-2023  润新知