OC学习笔记 - UI基础5

本章知识点:xib与storyboard的区别,xib的基本使用,xib的加载原理,渐变动画,调整UIButton内部子控件的位置,调整UIButton内边距,UIButton图片拉伸,KVC,KVO

xib与storyboard的区别

  1. 共同点:
    1 都用来描述软件界面
    2 都用Interface Builder工具来编辑
    3 本质都是转换成代码去创建控件
  2. 不同点:
    1 Xib是轻量级的,用来描述局部的UI界面
    2 Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系

xib的基本使用

  1. xib的加载
//方式一
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"xibname" owner:nil options:nil];
UIView *view = [[[NSBundle mainBundle] loadNibNamed:@"xibname" owner:nil options:nil] firstObject];
//方式二
UINib *nib = [UINib nibWithNibName:@"xibname" bundle:nil];
NSArray *views = [nib instantiateWithOwner:nil options:nil];
UIView *view = [[nib instantiateWithOwner:nil options:nil] firstObject];
[self.view addSubview:view];
  1. xib的使用
    注意事项:
    1 如果一个view从xib中加载,就不能用init和initWithFrame:方法创建
    2 如果一个xib经常被使用,应该提供快速构造类方法
    3 如果一个view从xib中加载,想用代码添加一些子控件,得在initWithCoder:和 awakeFromNib 创建
    4 如果一个view从xib中加载,会调用initWithCoder: 和awakeFromNib,不会调用init和initWithFrame:方法
//关联XYProView类
//XYProView.h
#import 
@interface XYProView: UIView
// 提供set方法
- (void)setIcon: (NSString *)icon;
- (void)setName: (NSString *)name;
// 提供快速创建方法
+ (instancetype)proView;
@end
//XYProView.m
#import "XYProView.h"
@interface XYProView ()
//在xib中创建(连线)
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
//注释代码为创建一个label子控件(用代码创建)      
//@property (nonatomic, weak) UILabel *label;
//毛玻璃
@property (nonatomic, weak) UIToolbar *toolBar;
@end

@implementation XYProView

/* 
     如果View从xib中加载,就不会调用init和initWithFrame:方法
      View从xib中加载时,会调用initWithCoder:方法
     注意: 如果子控件是从xib中创建,是处于未唤醒状态  
*/
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
      self = [super initWithCoder:aDecoder]) {
          //创建子控件
          /*
                UILabel *label = [[UILabel alloc] init];
                label.backgroundColor = [UIColor grayColor];
                label.text = @“text”;
               [self addSubview:label];
                self.label = label;
          */
     }
      return self;
}

//布局子控件
- (void)layoutSubviews{
     [super layoutSubviews];
     //self.label.frame = self.bounds;
      self.toolBar.frame = self.iconView.bounds;
}

//从xib中唤醒,添加xib中创建的子控件的子控件
- (void)awakeFromNib{
     //往imageView上加毛玻璃
      UIToolbar *toolBar = [[UIToolbar alloc] init];
     [self.iconView addSubview:toolBar];
      self.toolBar = toolBar;
}

//快速构造方法
+ (instancetype)proView{
      return [[[NSBundle mainBundle] loadNibNamed:@"XYproView" owner:nil options:nil] firstObject];
}

//设置数据
- (void)setIcon:(NSString *)icon{
      self.iconView.image = [UIImage imageNamed:icon];
}

- (void)setName:(NSString *)name{
      self.titleLabel.text = name;
}

@end

使用xib

XYProView *proView = [XYProView shopView];
proView.frame = CGRectMake(100, 100, 80, 100);  
//给子控件设置属性
[proView setName:@“name”];
[proView setIcon:@“icon”];    
[self.view addSubview:proView];

xib的加载原理

  1. xib的加载原理(伪代码)
- (UIView *)loadFormNib{
       XYproView *proView = [[XYProView alloc] initWithCoder:nil];
       proView.frame = CGRectMake(0, 0, 80, 100);
    
       UIImageView *iconView = [[UIImageView alloc] initWithCoder:nil];
       iconView.backgroundColor = [UIColor greenColor];
       iconView.frame = CGRectMake(0, 0, 80, 80);
       iconView.tag = 100;
      [proView addSubview:iconView];
       self.iconView = iconView;
    
       UILabel *label = [[UILabel alloc] initWithCoder:nil];
       label.backgroundColor = [UIColor orangeColor];
       label.tag = 200;
      [proView addSubview:label];
       self.titleLabel = label;
    
       return proView;
}

渐变动画

  1. 平移
    方式一:
        //点击按钮开始动画
- (IBAction)translate {                   
      //开始动画
      [UIView beginAnimations:nil context:nil];
      [UIView setAnimationDuration:1.0];
      //动画代码
       CGRect frame = self.animationView.frame;
       frame.origin.y -= 50;
       self.animationView.frame = frame;
      //提交动画
      [UIView commitAnimations];
}

方式二(三种方法):

- (IBAction)translate {  
      //1 动画代码
      [UIView animateWithDuration:2.0 animations:^{    
       CGRect frame = self.animationView.frame;
       frame.origin.y -= 50;
       self.animationView.frame = frame;
}];

      //2 动画代码
      [UIView animateWithDuration:1.0 animations:^{
              CGRect frame = self.animationView.frame;
              frame.origin.y -= 50;
              self.animationView.frame = frame;
      } completion:^(BOOL finished) {
            //动画完成后做什么事情
              self.animationView.backgroundColor = [UIColor blackColor];
      }];

      //3 动画代码    
      [UIView animateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{       
            /*
                    UIViewAnimationOptionCurveEaseInOut  动画开始/结束比较缓慢,中间相对较快
                    UIViewAnimationOptionCurveEaseIn     动画开始延时
                    UIViewAnimationOptionCurveEaseOut    动画完成后延时
                    UIViewAnimationOptionCurveLinear     匀速
            */                
             CGRect frame = self.animationView.frame;
             frame.origin.y += 50;
             self.animationView.frame = frame;
        
      } completion:^(BOOL finished) {
            //动画完成后做什么事情
              self.animationView.backgroundColor = [UIColor greenColor];
      }];
}
  1. 缩放
- (IBAction)scale {    
      [UIView animateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveEaseIn animations:^{     
             CGRect frame = self.animationView.frame;
             frame.size = CGSizeMake(10, 15);
             self.animationView.frame = frame;      
      } completion:^(BOOL finished) {
            //动画完成
      }];
}
  1. 透明度动画(嵌套)
- (IBAction)alpha {
      [UIView animateWithDuration:1.0 delay:0.5 options:UIViewAnimationOptionCurveEaseOut animations:^{
             self.animationView.alpha -= 0.9;
      } completion:^(BOOL finished) {
            [UIView animateWithDuration:2.0 animations:^{
                    self.animationView.alpha += 0.9;
          }];
     }];
}

调整UIButton内部子控件的位置

  1. 方式一:重写两个方法
//重写两个方法: 不要调用super,就是要重写掉
//contentRect: 内容的尺寸,内容包括(imageView和label)
- (CGRect)titleRectForContentRect:(CGRect)contentRect{
      return CGRectMake(0, 0, 100, 70);
}

- (CGRect)imageRectForContentRect:(CGRect)contentRect{
      return CGRectMake(100, 0, 70, 70);
}
  1. 方式二:重写layoutSubviews方法
- (void)layoutSubviews{
     [super layoutSubviews];
     // 设置子控件的位置
      self.titleLabel.frame = CGRectMake(0, 0, 100, 70);
      self.imageView.frame = CGRectMake(100, 0, 70, 70);
}
  1. 调整子控件
- (instancetype)initWithFrame:(CGRect)frame{
      if (self = [super initWithFrame:frame]) {
          // 文本居中
            self.titleLabel.textAlignment = NSTextAlignmentCenter;
          // 改变图片的内容模式
            self.imageView.contentMode = UIViewContentModeCenter;
     }
      return self;
}

调整UIButton内边距

  1. 设置整体内边距
    self.button.contentEdgeInsets = UIEdgeInsetsMake(-20, 0, 0, 0);
  2. 设置图片内边距
    self.button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
  3. 设置标题内边距
    self.button.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -10);

UIButton图片拉伸

  1. 方式一:
//默认为平铺
UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(imageHeight * 0.5, imageWidth * 0.5, imageHeight * 0.5 -1, imageWidth * 0.5 - 1)];
//UIImageResizingModeTile, 平铺
//UIImageResizingModeStretch, 拉伸(伸缩)
UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(imageHeight * 0.5, imageWidth * 0.5, imageHeight * 0.5 -1, imageWidth * 0.5 - 1) resizingMode:UIImageResizingModeTile];
  1. 方式二:
//stretchableImageWithLeftCapWidth  图片宽度 - 左边受保护区域 - 1 
//topCapHeight 图片高度 - 上方受保护区域 - 1 
UIImage *resizableImage = [image stretchableImageWithLeftCapWidth:imageWidth * 0.5 topCapHeight:imageHeight * 0.5];
  1. 一般我们将拉伸方法写在UIImage的分类中
#import "UIImage+XMGExtention.h"
@implementation UIImage (XMGExtention)
+ (instancetype)resizableImageWithLocalImageName:(NSString *)localImageName{
     // 创建图片对象
      UIImage *image = [UIImage imageNamed:localImageName];
     // 获取图片的尺寸
      CGFloat imageWidth = image.size.width;
      CGFloat imageHeiht = image.size.height;
     // 返回一张拉伸且受保护的图片
      return [image stretchableImageWithLeftCapWidth:imageWidth * 0.5 topCapHeight:imageHeiht * 0.5 ];
}
@end

KVC

  1. KVC:Key Value Coding,即键值编码
  2. 使用KVC进行赋值
[person setValue:@"王五" forKey:@"name"];
//forKeyPath可以进行自动类型转换
[person setValue:@"19" forKeyPath:@"money"];
[person.dog setValue:@"阿黄" forKey:@"name"];
[person setValue:@"旺财" forKeyPath:@"dog.name"]; 
//KVC可以修改类的私有成员变量(_age可以改为age)
[person setValue:@"88" forKeyPath:@"_age"] ;

forKey和forKeyPath的区别:
1 forKeyPath 包含了所有 forKey 的功能
2 forKeyPath 进行内部的点语法,层层访问内部的属性
3 注意: key值一定要在属性中找到

  1. 利用KVC取值
XMGPerson *person = [[XMGPerson alloc] init];
person.name = @“name”;
person.money = 12332;
NSLog(@"%@ --- %.2f", [person valueForKeyPath:@"name"], [[person valueForKey:@"money"] floatValue]);
  1. 字典转模型
    开发中不建议使用setValuesForKeysWithDictionary:
    1 字典中的key必须在模型的属性中找到,否则会报错
    2 如果模型中带有模型,setValuesForKeysWithDictionary无法使用
    应用场景: 简单的字典转模型
- (instancetype)initWithDict:(NSDictionary *)dict{
      if (self = [super init]) {
          //self.name = dict[@"name"];
          //self.money = [dict[@"money"] floatValue];
          [self setValuesForKeysWithDictionary:dict];
     }
      return self;
}
  1. 模型转字典
    NSDictionary *dict = [person dictionaryWithValuesForKeys:@[@"name", @"money"]];
  2. 取出数组中所有模型的某个属性值
XYPerson *person1 = [[XYPerson alloc] init];
person1.name = @“name1”;
person1.money = 22.99;     
XYPerson *person2 = [[XYPerson alloc] init];
person2.name = @“name2”;
person2.money = 122.99;
NSArray *allPersons = @[person1, person2];
NSArray *allPersonName = [allPersons valueForKeyPath:@"name"];

KVO

  1. KVO: Key Value Observing 键值监听,当某个对象的属性值发生改变的时候,用KVO监听
XYPerson *person = [[XYPerson alloc] init];
person.name = @“aaa”;    
/*
     作用:给对象绑定一个监听器(观察者)
     - Observer 观察者
     - KeyPath 要监听的属性
     - options 选项(方法方法中拿到属性值)
*/
[person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];   
person.name = @“bbb”;
// 移除监听
[person removeObserver:self forKeyPath:@"name"];
/*
     当监听的属性值发生改变
      keyPath 要改变的属性
      object  要改变的属性所属的对象
      change  改变的内容
      context 上下文
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
      NSLog(@“%@, %@, %@“, keyPath, object, change);    //改变的属性,所属对象,改变后的值
}

你可能感兴趣的:(OC学习笔记 - UI基础5)