iOS UI基础04

  • 动画

    • 1.头尾式动画 动画开始
      [UIView beginAnimations:nil context:nil];
      设置动画时间
      [UIView s !           etAnimationDuration:3];
      [UIView setAnimationDelegate:self];
      只要写在开始和结束之间的代码, 就会被执行动画
      但是: 并不是所有的代码都能够执行动画
      只有属性声明中说明了是animatable的属性,才可以执行UIView动画
      CGRect tempFrame2 = self.hudLabel.frame;
      tempFrame2.origin.y -= 100;
      self.hudLabel.frame = tempFrame2;
      self.hudLabel.alpha = 1.0;
      self.hudLabel.hidden = YES;
      动画结束
      [UIView commitAnimations];
      
    • 2.block式动画 Duration: 动画执行的时长 animations: 在block中写需要执行动画的代码 completion: 动画结束后系统会自动调用该block delay: 延迟多少秒

      [UIView animateWithDuration:2 animations:^{
          self.hudLabel.alpha = 1.0;
      }];
      
      [UIView animateWithDuration:1.0 animations:^{
          self.hudLabel.alpha = 1.0;
      } completion:^(BOOL finished) {
          NSLog(@"动画结束了");
      
          [UIView animateWithDuration:1.0 delay:1.0 options:kNilOptions animations:^{
              self.hudLabel.alpha = 0.0;
          } completion:nil];
      
      }];
      
  • UIAlertController HUD(提示框)
    • 继承UIViewController
    • 注意:
      • 如果UIAlertController的样式是ActionSheet, 就不能添加输入框
        // 1.创建一个AlertController
        // Title : 按钮上显示的文字
        // style: 按钮的样式
        // handler: 点击按钮之后的回调
        UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"标题" message:@"正文" preferredStyle:UIAlertControllerStyleActionSheet];
        UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * __nonnull action) {
        NSLog(@"点击了确定");
        }];
        UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * __nonnull action) {
        NSLog(@"点击了取消");
        }];
        [alertVc addAction:action1];
        [alertVc addAction:action2];
        // 2.显示
        [self presentViewController:alertVc animated:YES completion:nil];
        
        • 如果UIAlertController的样式是UIAlertControllerStyleAlert 就可以添加输入框
          // 添加一个输入框
          [alertVc addTextFieldWithConfigurationHandler:^(UITextField * __nonnull textField) {
          textField.text = @"用户名";
          NSLog(@"textField");
          }];
          
  • UIActionSheet

     // 1.创建UIActionSheet
      UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"哥是标题" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"确定" otherButtonTitles:@"其它", @"Other", nil];
      // 2.显示UIActionSheet
      [sheet showInView:self.view];
    
      // 只要UIActionSheet上的按钮被点击就会调用
      // actionSheet:谁触发事件就会把谁传递进来
      // clickedButtonAtIndex:当前被点击按钮的索引
      -(void)actionSheet:(nonnull UIActionSheet *)actionSheet      clickedButtonAtIndex:(NSInteger)buttonIndex
      {
        NSLog(@"%ld", buttonIndex);
      }
    
  • UIAlertView

          UIAlertView *alert = [[UIAlertView alloc]        initWithTitle:@"哥是标题" message:@"姐是正文..." delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
      alert.alertViewStyle =  UIAlertViewStyleLoginAndPasswordInput;
    
           [alert show];
    
    • 只要UIAlertView上的按钮被点击, 就会调用 alertView:谁触发事件就会把谁传递进来 ButtonAtIndex: 当前被点击按钮的索引
          -(void)alertView:(UIAlertView *)alertView    clickedButtonAtIndex:(NSInteger)buttonInde
         {
      // 取消 = 0, 确定 = 1 , 其他 = 2 , Other = 3 以此类推
      switch (buttonInde)
              {
          case 0:
              NSLog(@"点击了取消");
              break;
          case 1:
              NSLog(@"点击了确定");
              break;
          case 2:
              NSLog(@"点击了其他");
              break;
          case 3:
              NSLog(@"点击了Other");
              break;
          default:
              break;
             }
    
        }
    
  • 代理的应用场景

    • A对象向监听B对象的变化, A对象就可以成为B对象的代理 B对象发生一些变化想通知A对象, 那么A对象就可以成为B对象的代理

    • 监听

      • 规律:
        • 1.以后但凡看到iOS中需要传递对象成为某个对象的代理, 那么直接写上某个对象的类名 + Delegate即可
        • 2.一般情况下, 代理中的方法都是以控件的名称去掉前缀开头
  • 自定义HUD

    // 1.创建父控件
      UIView *cover = [[UIView alloc] init];
      cover.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
      cover.frame = CGRectMake(0, 0, 150, 150);
      cover.center = self.view.center;
    
      // 修改父控件为圆角
      cover.layer.cornerRadius = 10;
      [self.view addSubview:cover];
    
      // 2.创建菊花
      // 菊花有默认的尺寸
      // 注意: 虽然有默认的尺寸, 但是要想显示必须让菊花转起来
      UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
      activity.center = CGPointMake(cover.frame.size.width * 0.5, 50);
      [activity startAnimating];
    
      [cover addSubview:activity];
      // 3.创建UILabel
      UILabel *label = [[UILabel alloc] init];
      //    label.backgroundColor = [UIColor purpleColor];
      label.textAlignment = NSTextAlignmentCenter;
      label.text = @"正在拼命加载中...";
      label.frame = CGRectMake(0, cover.frame.size.height - 80, cover.frame.size.width, 80);
      [cover addSubview:label];
    
  • 自定义按钮

    • 注意: 不能在外界直接修改UIButton内部的子控件的frame
      这是不可以的
      XMGButton *btn = [[XMGButton alloc] init];
      btn.imageView.frame = CGRectMake(0, 0, btn.frame.size.width, btn.frame.size.width);
      
    • 需要在自定义按钮类实现中重写如下方法才可以修改UIButton内部的子控件的frame

      • 该方法用于返回按钮内部标题的尺寸和位置
      • 该方法是由系统自动调用的
      • 系统每次调用该方法, 都会将父控件的frame传递进来
      • contentRect: 父控件的frame
      • 该方法用于返回按钮内部的图片的尺寸和位置

        -(CGRect)imageRectForContentRect:(CGRect)contentRect
        {
          // x = 0, y = 0, width = 父控件的宽度, height =                       父控件的宽度
         return CGRectMake(0, 0, contentRect.size.width,         contentRect.size.width);;
         }
        
        -(CGRect)titleRectForContentRect:(CGRect)contentRect
        {
        // x = 0, y = 父控件的宽度 width =  父控件的宽度, height = 父控件的高度 - 父控件的宽度
        return CGRectMake(0, contentRect.size.width, contentRect.size.width, contentRect.size.height - contentRect.size.width);
        }
        
        • UIButton内部的子控件的frame还可以用-(void)layoutSubviews方法实现
    • UIButton内边距

      UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
      [btn setImage:[UIImage imageNamed:@"024"] forState:UIControlStateNormal];
      [btn setTitle:@"贵宾" forState:UIControlStateNormal];
      btn.frame = CGRectMake(100, 100, 145, 60);
      // 上左下右
      // 如果是设置contentEdgeInsets, 会把UIImageView和UIlabel当做一个整体移动
      // 如果是设置titleEdgeInsets/imageEdgeInsets. 那么不会影响到另外一个, 也就是只会改变当前设置的这个控件
      btn.contentEdgeInsets = UIEdgeInsetsMake(20, 0, 0, 0);
      btn.titleEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0);
      btn.imageEdgeInsets = UIEdgeInsetsMake(50, 0, 0, 00);
      [self.view addSubview:btn];
      
  • 图片拉伸

       UIButton *btn = [[UIButton alloc] init];
      UIImage *image = [UIImage imageNamed:@""];
    
      // 1.iOS5以前
    /*
      // LeftCapWidth: 左边多少不能拉伸
      // 右边多少不能拉伸 = 控件的宽度 - 左边多少不能拉伸 - 1
      //  right  =  width - leftCapWidth - 1
      // 1 = width - leftCapWidth - right
    
      // topCapHeight: 顶部多少不能拉伸
      // 底部有多少不能拉伸 = 控件的高度 - 顶部多少不能拉伸 - 1
      //  bottom =  height - topCapWidth - 1
      // 1 = height - topCapWidth - bottom
      UIImage *newImage = [image stretchableImageWithLeftCapWidth:5 topCapHeight:5];
    */
    
      // 2.iOS5开始
      /*
      // UIEdgeInsets是告诉系统哪些地方需要受保护, 也就是不可以拉伸
      // resizableImageWithCapInsets默认拉伸方式是平铺
      UIEdgeInsets insets = UIEdgeInsetsMake(image.size.height * 0.5, image.size.width * 0.5, image.size.height * 0.5, image.size.width * 0.5);
      UIImage *newImage =  [image resizableImageWithCapInsets:insets];
       */
    
      // 3.iOS6开始
      /*
      // resizingMode指定拉伸模式
      // 平铺
      // 拉伸
      UIEdgeInsets insets = UIEdgeInsetsMake(5, 5, 5, 5);
      UIImage *newImage =  [image resizableImageWithCapInsets:insets resizingMode:UIImageResizingModeStretch];
      */
      [btn setBackgroundImage:newImage forState:UIControlStateNormal];
      btn.frame = CGRectMake(100, 100, 200, 80);
      [self.view addSubview:btn];
    
  • KVC
        Person *p = [Person new];
        p.name = @"lmj";
        p.money = 998;

  #pragma mark 获取单个值
    NSString *name =[p valueForKey:@"name"];
    NSLog(@"name = %@",name);
    double money =[[p valueForKey:@"money"] doubleValue];
    NSLog(@"money = %f", money);


   #pragma mark 获取多层值
   NSString *dogName = [p valueForKey:@"dog.name"];
   NSString *dogName = [p valueForKeyPath:@"dog.name"];
   NSLog(@"dogName = %@", dogName);

    #pragma mark 模型转字典
    NSDictionary *dict = [p dictionaryWithValuesForKeys:@[@"name",       @"money"]];
    NSLog(@"%@", dict);


   #pragma mark 获取数组中对象的值

    Person *p1 = [Person new];
    p1.name = @"zs";
    p1.money = 111;

    Person *p2 = [Person new];
    p2.name = @"ls";
    p2.money = 222;

    Person *p3 = [Person new];
    p3.name = @"ww";
    p3.money = 666;

    NSArray *arr = @[p1, p2, p3];

    // 如果数组中的元素都是同一种类型的数据,  可以使用KVC获取数组中所有对象的某个属性的值
    NSArray *res = [arr valueForKeyPath:@"name"];
    NSLog(@"res = %@", res);


  #pragma mark 运算符
    id res1 = [arr valueForKeyPath:@"@avg.money"];
    NSLog(@"res = %@", res1);

}

- (void)kvcSetter
{
    Person *p = [[Person alloc] init];
    //    p.name = @"lnj"; // setter
    //    p.money = 998.0;
#pragma mark 单个值
    /*
     //      KVC == KEY VALUE CODING
     // Value : 值, 只能传对象
     // forKey: 需要给谁(哪个属性)赋值
     // setValue:forKey:方法, 只能给对象的直接属性赋值
     [p setValue:@"lmj" forKey:@"name"];
     // @(998.0) == [NSNumber numberWithDouble:(double)]
     [p setValue:@(668.0) forKey:@"money"];
     */

#pragma mark 多层赋值
    p.dog = [Dog new];
    /*
     //    p.dog.name == [[p dog] setName:]
     //    p.dog.name = @"wangwang";
     //    p.dog.price = 110.0;
     // setValue:forKeyPath: 可以给对象的间接属性赋值. 多层赋值
     // 建议: 以后在开发中都使用setValue:forKeyPath:
     //    [p setValue:@"xiaoqiang" forKeyPath:@"dog.name"];
     //    [p setValue:@(110) forKeyPath:@"dog.price"];
      */
#pragma mark 给私有成员变量赋值
    /*
     //    [p setValue:@"lnj" forKey:@"_name"];
     //    [p setValue:@(30) forKey:@"_age"];

     //    SEL sel = @selector(say);
     //    [p performSelector:sel];
     //    [p say];
     */

#pragma mark 字典转模型

    NSDictionary *dict = @{
                           @"name":@"xxx",
                           @"money": @(998.1),
                           //                           @"score":@(100)
                           @"dog":@{
                                   @"name":@"wangcai",
                                   @"price":@(110)
                                   }
                           };

    //    p.name = dict[@"name"];
    //    p.money =[dict[@"money"] doubleValue];


    // 注意点:
    // 1.如果想使用KVC进行字典转模型, 那么字典中的key必须和模型中的属性一模一样(个数 + 名称)
    //  this class is not key value coding-compliant for the key score.'
    // 2.如果使用KVC进行字典转模型, 只能对当前调用KVC方法的对象进行转换, 不能对它的属性的对象进行转换

    // setValuesForKeysWithDictionary:方法内部的实现原理
    // 1.会拿到字典中的key, 然后根据这个key取出字典中的值, 然后再根据这个key赋值给对象
    //   [p setValue:@"xxx" forKey:@"name"];
    [p setValuesForKeysWithDictionary:dict];

    NSLog(@"p.dog = %@", p.dog);

    NSLog(@"name = %@, money = %f", p.name, p.money
  • KVO
     //    KVO == Key Value Observing
//    作用: 可以监听某个对象属性的改变

    Person *p = [Person new];
    p.name = @"lnj";
    p.age = 30;

    /*
     第一个参数: 告诉系统哪个对象监听
     第二个参数: 监听当前对象的哪个属性
     第三个参数: 监听到属性改变之后, 传递什么值
     第四个参数: 需要传递的参数 (这个参数不是传递给属性的)
     */
    // 给p这个对象添加一个监听 , 监听p对象的age属性的改变, 只要age属性改变就通知self
    [p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];

    p.age = 50;

    NSLog(@"-------------------");

//    p.age = 100;

    // 注意: 如果使用KVO监听某个对象的属性, 当对象释放之前一定要移除监听
    //  reason: 'An instance 0x7f9483516610 of class Person was deallocated while key value observers were still registered with it.
    // 注意: KVO只能监听通过set方法修改的值
    /*
     KVO的原理:
     只要给一个对象注册一个监听, 那么在运行时, 系统就会自动给该对象生成一个子类对象,
     并且重写自动生成的子类对象的被监听属性的set方法, 然后在set方法中通知监听者
     NSKVONotifying_Person
     */
    p->_age = 998;

    // 从p对象上移除self对它的age属性的监听
    [p removeObserver:self forKeyPath:@"age"];

 // 只要监听到属性的改变就会调用
// keyPath: 被监听的属性名称
// object : 被监听的对象
// context: 注册监听的时候传入的值
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary *)change context:(nullable void *)context
{
    NSLog(@"keyPath = %@, object = %@ , change = %@, context = %@", keyPath, object, change, context);
}
posted @ 2015-08-02 23:19  刘娇贤  阅读(232)  评论(0编辑  收藏  举报