因为作android开发时间比较长,按照android的经验,通常开发界面都是使用xml来写布局文件的,不多会彻底使用代码来写布局,最近刚学iOS,发现好多都是直接使用代码来写布局的。看视频学习恰好看到这个不错的小项目,所以作了一点小小的整理。android
要实现的效果以下,点击加号添加一条,点击回收投标删除最下面一条,点击删除会删除当前的一条。点击头片会更改中间的文字。删除/添加会伴随动画。dom
点击添加按钮ide
- (IBAction)add:(UIBarButtonItem *)sender{ UIView * v = [self getRowView]; UIView * lastView = [[self.view subviews] lastObject]; NSLog(@"%@",lastView); CGFloat rowY = lastView.frame.origin.y + lastView.frame.size.height + 1; v.frame = CGRectMake(_screenWidth, rowY, _screenWidth, KHeight); v.alpha = 0; [self.view addSubview:v]; [UIView animateWithDuration:0.5 animations:^{ v.alpha = 1; v.frame = CGRectMake(0, rowY, _screenWidth, KHeight); }]; [self.removeItem setEnabled:true]; }
点击回收最后面一条按钮
函数
- (IBAction)remove:(UIBarButtonItem *)sender { UIView * lastView = [[self.view subviews] lastObject]; [UIView animateWithDuration:0.5 animations:^{ CGRect tempF = lastView.frame; tempF.origin.x = _screenWidth; lastView.frame = tempF; lastView.alpha = 0; } completion:^(BOOL finished) { [lastView removeFromSuperview]; [self.removeItem setEnabled:self.view.subviews.count > 1]; }]; }getRowView函数是获得一行item的布局View
- (UIView *) getRowView { UIView * view = [[UIView alloc]init]; view.bounds = CGRectMake(0, 0, self.view.frame.size.width, KHeight); [view setBackgroundColor:[UIColor grayColor]]; // 建立文字 UILabel * label = [[UILabel alloc]init]; label.frame = CGRectMake(0, 0, self.view.frame.size.width, KHeight); label.text =_allNames[arc4random_uniform(_allNames.count)]; label.textColor = [UIColor blackColor]; label.textAlignment = NSTextAlignmentCenter; label.tag = 10; [view addSubview:label]; // 建立头像 UIButton * icon = [[UIButton alloc]init]; icon.frame = CGRectMake(20, 0, KHeight , KHeight); int randomIndex = arc4random_uniform(9); NSString *iconName = [NSString stringWithFormat:@"01%d.png", randomIndex]; // 设置图片 [icon setImage:[UIImage imageNamed:iconName] forState:UIControlStateNormal]; // 添加监听器 [icon addTarget:self action:@selector(iconClick:) forControlEvents:UIControlEventTouchUpInside]; [view addSubview:icon]; // 建立删除按钮 UIButton * deleteIcon = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [deleteIcon setCenter:CGPointMake(280, KHeight/2)]; deleteIcon.bounds = CGRectMake(0, 0, 60 , 30); [deleteIcon setTitle:@"删除" forState:UIControlStateNormal]; [deleteIcon addTarget:self action:@selector(deleteClick:) forControlEvents:UIControlEventTouchUpInside]; [view addSubview:deleteIcon]; return view; }点击图片的响应函数
- (void)iconClick:(UIButton *)btn { UILabel * label = (UILabel *)[[btn superview] viewWithTag:10]; NSString * oriStr = [label text]; NSString * newStr = [NSString stringWithFormat:@"%@+%@",oriStr,oriStr]; label.text = newStr; }点击删除某一项的按钮
- (void) deleteClick:(UIButton * )btn { [UIView animateWithDuration:0.5 animations:^{ CGRect tempF = [btn.superview frame]; tempF.origin.x = _screenWidth; btn.superview.frame = tempF; } completion:^(BOOL finished) { // 将下面的全部项向上移动 int startIndex = [self.view.subviews indexOfObject:btn.superview]; [btn.superview removeFromSuperview]; [UIView animateWithDuration:0.5 animations:^{ for (int i = startIndex; i < self.view.subviews.count; i++) { UIView *child = self.view.subviews[i]; CGRect tempF = child.frame; tempF.origin.y -= KHeight + 1; child.frame = tempF; } }]; }]; }能够看出来彻底使用代码来写布局很是的麻烦,使用storyboard拖控件能够经过连线的方式减小代码量,上面的代码中,添加一条item的内容很是繁琐。
好处:不须要本身使用代码进行这一行的布局布局
缺点:存在的问题是还须要经过代码添加点击事件。学习
- (UIView *) getRowView { NSArray * views = [[NSBundle mainBundle] loadNibNamed:@"item" owner:nil options:nil]; UIView * view = views[0]; UIButton * icon = view.subviews[0]; UILabel * label = view.subviews[1]; UIButton * deleteIcon = view.subviews[2]; NSLog(@"%@ + %@ + %@",icon,label,deleteIcon); NSString *iconName = [NSString stringWithFormat:@"01%d.png",arc4random_uniform(9)]; [icon setImage:[UIImage imageNamed:iconName] forState:UIControlStateNormal]; label.text = _allNames[arc4random_uniform(_allNames.count)]; [deleteIcon addTarget:self action:@selector(deleteClick:) forControlEvents:UIControlEventTouchUpInside]; return view; }
好处:不须要本身添加点击事件的触发。指定了FileOwer,FileOwer保证了能够连线,指定某个xib的FileOwer也就是指定了它的管理类。动画
缺点:这样存在的问题是代码间的耦合性过高,spa
理论上在建立一行时,也就是在getRowView方法里面,并不须要关注具体的细节,不须要关注他的子控件,最好的状况就是只给传递咱们须要显示的数据,剩下的本身不须要处理。而且很差实现代码的复用。code
注:必须指定File’s Ower 不然没法连线,而且在使用代码加载的时候指定该参数。FileOwer并不必定要是这个类,任何一个类都是能够的。orm
- (UIView *) getRowView { NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"item" owner:self options:nil]; UIView *view = views[0]; UIButton * icon = view.subviews[0]; UILabel * label = view.subviews[1]; NSString *iconName = [NSString stringWithFormat:@"01%d.png", arc4random_uniform(9)]; [icon setImage:[UIImage imageNamed:iconName] forState:UIControlStateNormal]; label.text = _allNames[arc4random_uniform(_allNames.count)]; return view; }
注意:这里不能指定File Owner的属性,将View的Class属性设置为咱们自定义的View便可连线。
MyView中的类方法以下
+ (MyView *) myViewWithIcon:(UIImage *)iconImage andLabel:(NSString *)labelStr { MyView *view = [[NSBundle mainBundle] loadNibNamed:@"item" owner:nil options:nil][0]; [view.iconBtn setImage:iconImage forState:UIControlStateNormal]; view.label.text = labelStr; return view; }
这样建立一行View的代码为
- (UIView *) getRowView { MyView * view = [MyView myViewWithIcon:[UIImage imageNamed:[NSString stringWithFormat:@"01%d.png", arc4random_uniform(9)]] andLabel:_allNames[arc4random_uniform(_allNames.count)]]; return view; }
使用MyView来建立一行View时就能够彻底和其余的代码分开,由于处理它的子控件的业务所有由他本身来处理。
以上内容整理自视频