iOS,Android,Java培训,期待与您的交流
iOS应用开发的一项内容就是用户界面的开发。不管应用程序实际包含的逻辑有多复杂,如果这个应用程序没有提供友好的图形用户界面,將很难吸引用户。作为一个程序设计者,必须优先考虑用户的感受,一定要让用户感到爽,这个应用程序才有价值。
xib是早期iOS开发的界面设计文件,从iOS5开始,Xcode使用比xib更近一步的StoryBoard来设计UI界面。但是xib并没有被淘汰,在iOS开发中,某些界面的开发必须用到xib。总体而言,storyboard和xib的用法遵循如下规则:
storyboard,描述软件界面,大范围,重量级,比较适合整个软件的所有界面
xib:描述软件界面,小范围,轻量级,适合描述小界面
1 xib的基本使用
xib的使用与StroyBoard大同小异,一样需要拖控件到界面。但需要特别注意的时,xib文件有一个file owner选项。该file owner一般是一个类,xib中控件的事件监听方法必须是该file owner的方法,即如果没有指定file owner是没法用连线指定控件的监听方法(可以用addTarget方法)。用代码加载xib文件时,也要指定一个file owner对象。两个file onwer的意义不同,前者是为了绑定监听方法,后者是运行时,系统才会真正调用在代码中指定的file owner的监听方法。下面是一个xib的界面,只包含一个按钮,指定该xib的file owner是一个Dog类,监听方法是- (IBAction)btnClick;
用代码加载xib时,可以指定file owner为Dog实例,也可以不指定。如果不指定,单击按钮时,将会调用nil的btnClick;方法,会导致EXC_BAD_ACCESS错误。也不能指定局部变量,因为局部变量在它所在的方法结束后,该局部变量就不存在了,也会导致EXC_BAD_ACCESS错误
- (void)viewDidLoad
{
[super viewDidLoad];
_d1 = [[Dog alloc] init]; //成员变量
_d1.age = 10;
_d2 = [[Dog alloc] init]; //成员变量
_d2.age = 20;
Dog *d = [[Dog alloc] init]; //局部变量
//加载xib文件,xib的file owner不能是局部变量。file owner也能为空,但会导致EXC_BAD_ACCESS错误
UIView *blueView = [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:_d2 options:nil][0];
//UIView *blueView = [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:nil options:nil][0];
blueView.center = CGPointMake(160, 200);
[self.view addSubview:blueView];
}
2 xib的重用
给xib指定file owner,降低了程序的耦合性。而且在程序中硬编码,加载xib文件,也不是一个好的编程方式。可以將xib抽象成一个类,调用该类的某个方法创建xib。以下面的xib界面为例,说明如何重用xib。
该界面的左边是一个图片按钮,中间是UILabel,右边是删除按钮。只要指定图片按钮的图片,和UILabel的现实文本,就能得到该xib代表的界面。
//RowView.h
@interface RowView : UIView
//类方法,用于创建xib界面
+ (id)rowViewWithIcon:(NSString *)icon name:(NSString *)name;
@property (nonatomic, weak) IBOutlet UIButton *iconBtn; //图片按钮
@property (nonatomic, weak) IBOutlet UILabel *nameLabel; //联系人姓名
@end
//RowView.m
@implementation RowView
+ (id)rowViewWithIcon:(NSString *)icon name:(NSString *)name
{
RowView *view = [[NSBundle mainBundle] loadNibNamed:@"RowView" owner:nil options:nil][0];
// 1.设置图标
// UIButton *iconBtn = (UIButton *)[view viewWithTag:1];
[view.iconBtn setImage:[UIImage imageNamed:icon] forState:UIControlStateNormal];
// 2.设置姓名
// UILabel *nameLabel = (UILabel *)[view viewWithTag:2];
view.nameLabel.text = name;
return view;
}
@end
3 联系人管理
用一个联系人管理的实例,说明如何应用xib和StoryBoard开发应用程序。联系人管理的界面如下图所示。
上图的UIToolBar是固定的,可以用StroyBoard创建,红色的联系人信息是不断变化,用xib创建。该xib对应的类已经在上文给出。当点击添加按钮时,增加一条联系人信息,通过监听事件方法实现。
#pragma mark 添加一行
- (IBAction)add:(UIBarButtonItem *)sender {
// 0.取出最后一个子控件
UIView *last = [self.view.subviews lastObject];
// 这行的Y = 最后一个子控件的Y + 最后一个子控件的高度 + 间距
CGFloat rowY = last.frame.origin.y + last.frame.size.height + 1;
// 1.创建一行
UIView *rowView = [self createRowView];
// 2.添加一行到控制器的view中
[self.view addSubview:rowView];
// 3.让删除item有效
_removeItem.enabled = YES;
// 4.执行动画
rowView.frame = CGRectMake(320, rowY, 320, kRowH);
rowView.alpha = 0;
// 4.1.开始动画
[UIView animateWithDuration:kDuration animations:^{
rowView.frame = CGRectMake(0, rowY, 320, kRowH);
rowView.alpha = 1;
}];
}
#pragma mark 创建一行(从xib中加载一行的view)
// xib == nib
- (UIView *)createRowView
{
NSString *icon = [NSString stringWithFormat:@"01%d.png", arc4random_uniform(9)];
NSString *name = _allNames[arc4random_uniform(_allNames.count)];
RowView *rowView = [RowView rowViewWithIcon:icon name:name];
return rowView;
}
点击UIToolBar的删除按钮,删除最后一个联系人,监听事件方法如下。
#pragma mark 删除一行
- (IBAction)remove:(UIBarButtonItem *)sender {
// 1.取出最后一个子控件
UIView *last = [self.view.subviews lastObject];
[UIView animateWithDuration:kDuration animations:^{
CGRect tempF = last.frame;
tempF.origin.x = 320;
last.frame = tempF;
last.alpha = 0;
} completion:^(BOOL finished) {
[last removeFromSuperview];
// 剩下的子控件个数 > 1就能够点击“删除”
_removeItem.enabled = self.view.subviews.count > 1;
}];
}
点击联系人信息的删除按钮,删除该行,后面的行自动向上填充。
#pragma mark 监听删除按钮点击
- (void)deleteClick:(UIButton *)btn
{
[UIView animateWithDuration:kDuration animations:^{
CGRect tempF = btn.superview.frame;
tempF.origin.x = 320;
btn.superview.frame = tempF;
btn.superview.alpha = 0;
} completion:^(BOOL finished) {
// 1.获得即将删除的这行在数组中的位置
int startIndex = [self.view.subviews indexOfObject:btn.superview];
// 2.删除当前行
[btn.superview removeFromSuperview];
[UIView animateWithDuration:0.3 animations:^{
// 3.遍历后面的子控件
for (int i = startIndex; i 1;
}];
}
iOS,Android,Java培训,期待与您的交流