UI基础

作者: CoderZXS | 来源:发表于2017-02-10 13:36 被阅读0次

    框架介绍

    • QuartzCore:核心动画框架,用来做游戏的
    • Mapkit:地图框架,打车软件常用
    • CoreLocation:核心定位,QQ说说,外卖软件

    代码仓库

    存储不同版本应用程序代码,用于对比修改了那些地方,当新的代码出现问题,可以回退到上一个版本。包含svn/git两种

    方法、属性与对象关系

    • 一个按钮可以连接多个方法,一个对象连接多个属性是没有必要的,只需要连接一个属性即可
    • 判断一个对象是否能够连线方法,需要看该对象的类是否继承于UIControl或者右键该对象看他是否包含sent events单词
    • NSSelectorFromString(NSString * _Nonnull aSelectorName):用于将字符串转化成方法
    • 只要方法名带有file的,都是传全路径
    • 如何抽方法
    • 先把相同的代码抽到方法中,不要设置方法名和参数
    • 把要变化的东西换成变量,然后编译,把报错的设置为方法的参数
    • 接口方法


      Snip20170122_48.png

    控件

    • 孙子控件不是子控件,也就是说子控件的子控件不是我的子控件
    • 只要控件有父控件,就一定能够从父控件中移除
    • 控制器的view默认包含屏幕上下20像素高度的子控件,可以通过取消勾选去除子控件,如下图


      Snip20160103_41.png
    "<_UILayoutGuide: 0x7fd0d4603820; frame = (0 0; 0 0); hidden = YES; layer = <CALayer: 0x60800003c040>>":
    
    • 每个控件都是个容器,能容纳其他控件

    Tag

    • tag:控件的ID,父控件可以通过tag来找到对应子控件
    • 根据一个tag标识找出对应的控件(一般指子控件)
    -(UIView *)viewWithTag:(NSInteger)tag;
    
    • 尽量少使用tag,原因如下:
      • tag的效率非常差
    • tag使用多了容易乱
    • tag执行伪代码如下图:


      Snip20160103_46.png

    位置和尺寸

    • bounds:通过bounds改变尺寸,在iOS9以后,中心点不变向四周延伸
    • 结构体是值传递,不是地址传递

    UIViewController的使用

    • 作用:负责处理软件界面的各种事件,并负责软件界面的创建和销毁
    • 注意:每一个控制器都会专门管理一个软件界面
    • 每一个控制器(UIViewController)内部都有个默认的UIView属性

    UIImageView

    Snip20170119_59.png Snip20170119_58.png Snip20170119_56.png
    • 判断图片控件是否在执行动画


      Snip20170119_67.png
    • 通过ARGB设置图片的背景色


      Snip20170119_71.png
    • 沙盒路径


      Snip20170119_61.png
    • animationRepeatCount:动画的播放次数(默认是0,代表无限播放
    • 其实UIImageView、UILabel也可以通过手势识别器来监听

    UIButton

    • highlighted(高亮状态)
      • 按钮被按下去的时候(手指还未松开)
      • 为了保证高亮状态下的图片正常显示,必须设置按钮的type为custom
    • UIButtonTypeCustom:无类型,按钮的内容需要自定义
    • 设置按钮的文字字体(需要拿到按钮内部的label来设置)
    btn.titleLabel.font =[UIFont systemFontOfSize:13];
    
    • 获得按钮的文字

    -(NSString *)titleForState:(UIControlState)state;

    - 获得按钮的文字颜色
    
    • (UIColor *)titleColorForState:(UIControlState)state;
    - 获得按钮内部的小图片
    
    • (UIImage *)imageForState:(UIControlState)state;
    - 获得按钮的背景图片
    
    - (UIImage *)backgroundImageForState:(UIControlState)state;
    
    * 直接通过addTarget...方法监听点击
    ![Snip20170121_21.png](https://img.haomeiwen.com/i1609505/ce999b319c1622ef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    * 创建UIButton
    ![Snip20170121_18.png](https://img.haomeiwen.com/i1609505/1293f5b01cf3773f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    * 设置按钮字体偏移量
    ![Snip20170121_19.png](https://img.haomeiwen.com/i1609505/d7209fdaad2cfbd6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    #九宫格
    ![Snip20170121_29.png](https://img.haomeiwen.com/i1609505/0c3de0d9110949de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![Snip20170121_22.png](https://img.haomeiwen.com/i1609505/4f12459c998c4405.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![Snip20170121_23.png](https://img.haomeiwen.com/i1609505/3d4cf47e1fc6e09a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    #UILabel
    * numberOfLines:文字行数
    * lineBreakMode:换行模式
    * 要想让UILabel自动换行,设置Lines为0即可
    
    #模型
    * 所谓模型,其实就是数据模型,专门用来存放数据的对象
    
    #手机尺寸
    ![尺寸.jpeg](https://img.haomeiwen.com/i1609505/10c69a4fc36feb62.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    #view的封装
    * 如果一个view内部的子控件比较多,一般会考虑自定义一个view,把它内部子控件的创建屏蔽起来,不让外界关心
    * 外界可以传入对应的模型数据给view,view拿到模型数据后给内部的子控件设置对应的数据
    * 代码-自定义封装控件的基本步骤:
      * 在initWithFrame:方法中添加子控件,初始化子控件,提供便利构造方法
      * 在layoutSubviews方法中设置子控件的frame(一定要调用super的layoutSubviews)
     * 给子控件设置数据,对外增加模型对象属性,在模型属性set方法中设置数据到子控件上
    * xIb自定义封装控件的基本步骤:
     * 新建自定义控件类
    ![Snip20170120_6.png](https://img.haomeiwen.com/i1609505/18f476c7aaf84fc8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
     * 新建xib文件(文件名建议和view的类名一致)
    ![Snip20170120_1.png](https://img.haomeiwen.com/i1609505/e0553de9e76eb509.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    ![0001.jpg](https://img.haomeiwen.com/i1609505/254bc3a5f19b6b04.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
      * 修改xib中view的类名
    ![Snip20170120_2.png](https://img.haomeiwen.com/i1609505/40a82d63b337faa8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
     * 封装xib的加载过程
    ![Snip20170120_3.png](https://img.haomeiwen.com/i1609505/27cbf2b37c9cf45f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    ![Snip20170120_4.png](https://img.haomeiwen.com/i1609505/385e141a3ee1aad7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
     * 增加模型属性,在模型属性set方法中设置数据到子控件上
     * Xib是轻量级的,用来描述局部的UI界面
    * Xib的加载
     * 方法1
    

    NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"xib文件名" owner:nil options:nil]

     * 方法2
    

    UINib *nib = [UINib nibWithNibName:@"xib文件名" bundle:nil];
    NSArray *views = [nib instantiateWithOwner:nil options:nil];

    * Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系
    * 一个控件有2种创建方式
      * 通过代码创建
          * 初始化时一定会调用initWithFrame:方法
     * 通过xib\storyboard创建
         * 初始化时不会调用initWithFrame:方法,只会调用initWithCoder:方法
        
       * 初始化完毕后会调用awakeFromNib方法
    * 有时候希望在控件初始化时做一些初始化操作,比如添加子控件、设置基本属性
    * 这时需要根据控件的创建方式,来选择在initWithFrame:、initWithCoder:、awakeFromNib的哪个方法中操作
    
    #颜色认知
    ![Snip20170121_7.png](https://img.haomeiwen.com/i1609505/1b471c932e2dbfdd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![Snip20170121_8.png](https://img.haomeiwen.com/i1609505/2214608c98e22a6e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![Snip20170121_9.png](https://img.haomeiwen.com/i1609505/5527a3bbd74df85e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![Snip20170121_10.png](https://img.haomeiwen.com/i1609505/13a9c76165598f4e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![Snip20170121_11.png](https://img.haomeiwen.com/i1609505/a4d22ad05169fadb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![Snip20170121_13.png](https://img.haomeiwen.com/i1609505/d598dc2b2dc1d91d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![Snip20170121_14.png](https://img.haomeiwen.com/i1609505/6c8597bbb0c294bb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![Snip20170121_16.png](https://img.haomeiwen.com/i1609505/1b8d26a8374449bd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    #Autolayout
    * 屏幕
     * 屏幕是由无数个点组成的,点又是由像素组成的
     * 非retina屏幕:1个点由1个像素组成
     * 0retina屏幕:1个点由4个像素组成
    * Autolayout的警告和错误
     * 警告
       * 控件的frame不匹配所添加的约束
       * 比如约束控件的宽度为100, 而控件现在的宽度是110
    
      * 错误
       - 缺乏必要的约束
         * 比如只约束了宽度和高度, 没有约束具体的位置
       * 两个约束冲突
         * 比如1个约束控件的宽度为100, 1个约束控件的宽度为110
    * 代码实现Autolayout的注意点
       * 要先禁止autoresizing功能,设置view的下面属性为NO
    

    view.translatesAutoresizingMaskIntoConstraints = NO;

    
     * 不用再给view设置frame
    * 创建约束对象的常用方法
      * view1 :要约束的控件
      * attr1 :约束的类型(做怎样的约束)
     * relation :与参照控件之间的关系
     * view2 :参照的控件
     * attr2 :约束的类型(做怎样的约束)
     * multiplier :乘数
     * c :常量
    

    +(id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;

    * 添加约束的规则
       * 对于两个同层级view之间的约束关系,添加到它们的父view上
    ![12.png](https://img.haomeiwen.com/i1609505/13e7e8547ea796cd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
     * 对于两个不同层级view之间的约束关系,添加到他们最近的共同父view上
    ![23.png](https://img.haomeiwen.com/i1609505/8d65c0ec02bc8924.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
     * 对于有层次关系的两个view之间的约束关系,添加到层次较高的父view上
    ![3333.png](https://img.haomeiwen.com/i1609505/a378eaacd52820d1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    * VFL示例
      - canelButton宽72,acceptButton宽50,它们之间间距12
    
     - H:[cancelButton(72)]-12-[acceptButton(50)]
    
      -  wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束越先被满足)
    
    • H:[wideView(>=60@700)]
      
     - 竖直方向上,先有一个redBox,其下方紧接一个高度等于redBox高度的yellowBox
    
    - V:[redBox][yellowBox(==redBox)]
    
      -  水平方向上,Find距离父view左边缘默认间隔宽度,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边缘的间距都是默认宽度。(竖线“|” 表示superview的边缘)
    
      - H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
    
    
    * 使用VFL来创建约束数组
       * format :VFL语句
       * opts :约束类型
       * metrics :VFL语句中用到的具体数值
       * views :VFL语句中用到的控件
       * 创建一个字典(内部包含VFL语句中用到的控件)的快捷宏定义
    
      - (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;
         NSDictionaryOfVariableBindings(...)
    
    * 基于Autolayout的动画
        - 在修改了约束之后,只要执行下面代码,就能做动画效果
    
      [UIView animateWithDuration:1.0 animations:^{
      [添加了约束的view的父控件 layoutIfNeeded];
    

    }];

    * Masonry
       - mas\_equalTo和equalTo
         * 默认情况下     
             * mas\_equalTo有自动包装功能,比如自动将20包装为@20
             * equalTo没有自动包装功能
             * 如果添加了下面的宏,那么mas\_equalTo和equalTo就没有区别
    
    #define MAS_SHORTHAND_GLOBALS
    

    // 注意:这个宏一定要添加到#import "Masonry.h"前面

    
     - mas\_width和width
       * 默认情况下
         * width是make对象的一个属性,用来添加宽度约束用的,表示对宽度进行约束
         -  mas\_width是一个属性值,用来当做equalTo的参数,表示某个控件的宽度属性
         * 如果添加了下面的宏,mas\_width也可以写成width
    

    define MAS_SHORTHAND

    * mas\_height、mas\_centerX以此类推
      * 可有可无的用法
          * 以下方法都仅仅是为了提高可读性,可有可无
    
      -(MASConstraint *)with {
     return self;
    

    }

     - (MASConstraint *)and {
    return self;
    

    }

    
    * 约束的动画
      * 先改变约束对象的值:
    

    self.redViewW.constant = 50;

     * 然后刷新整个视图
    

    [UIView animateWithDuration:2.0 animations:^{
    // 强制刷新
    [self.view layoutIfNeeded];
    }];

    * UILabel实现包裹内容
     * 设置宽度约束<= 固定值
     * 设置位置约束
     * 不需要设置高度约束
     * 万能公式
    

    obj1.property1 =(obj2.property2 * multiplier)+ constant value

    
    #UIScrollView
    ![Snip20170126_76.png](https://img.haomeiwen.com/i1609505/474e79dff8a45bc8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    ![Snip20170126_78.png](https://img.haomeiwen.com/i1609505/b07066abe4a08973.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    ![Snip20170126_79.png](https://img.haomeiwen.com/i1609505/2b3d68a17bc5b949.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    ![Snip20170127_81.png](https://img.haomeiwen.com/i1609505/4d3f78969d36162e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    #控制器view的延迟加载
    - 控制器的view是延迟加载的:用到时再加载
    - 可以用isViewLoaded方法判断一个UIViewController的view是否已经被加载
    - 控制器的view加载完毕就会调用viewDidLoad方法
    
    #总结
    * 先搭建界面,然后向服务器发送请求,获取网络数据,解析网络数据(xml/json),将其分别转换成模型数据,以数组方式存储,最后遍历显示到相应控件上去。
    * 重复代码需要抽方法
    * 可以考虑将经常变的数据放在文件中进行存储,程序启动后从文件中读取最新的数据。如果要变动数据,直接修改数据文件即可,不用修改代码

    相关文章

      网友评论

          本文标题:UI基础

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