- iPhone UIKit详解
- 王志刚 王中元 朱蕾编著
- 2090字
- 2020-08-28 08:00:21
2.3 UIView嵌套
2.3.1 追加子元素
UIView中拥有addSubView:这样的实例方法,可以在UIView中追加UIView作为子元素。当然UILabel及UIButton等UIView的子类也可以使用addSubView:方法自由地追加。这里首先看一个实例,在UIButton中使用addSubView:方法追加子元素的UIButton。
// 追加1-1按钮 UIButton* button11 = [UIButton buttonWithType:UIButtonTypeRounde dRect]; button11.frame = CGRectMake(10,10,300,300); [button11 setTitle:@”1-1” forState:UIControlStateNormal]; [button11 addTarget:self action:@selector(button11DidPush:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button11]; // 追加1-1-1按钮 UIButton* button111 = [UIButton buttonWithType:UIButtonTypeRound edRect]; button111.frame = CGRectMake(20,20,260,100); [button111 setTitle:@”1-1-1” forState:UIControlStateNormal]; [button111 addTarget:self action:@selector(button111DidPush:) forControlEvents:UIControlEventTouchUpInside]; [button11 addSubview:button111]; // 追加1-1-2按钮 UIButton* button112 = [UIButton buttonWithType:UIButtonTypeRound edRect]; button112.frame = CGRectMake(20,180,260,100); [button112 setTitle:@”1-1-2” forState:UIControlStateNormal]; [button112 addTarget:self action:@selector(button112DidPush:) forControlEvents:UIControlEventTouchUpInside]; [button11 addSubview:button112]; // 追加1-1-2-1按钮 UIButton* button1121 = [UIButton buttonWithType:UIButtonTypeRoun dedRect]; button1121.frame = CGRectMake(10,10,95,80); [button1121 setTitle:@”1-1-2-1” forState:UIControlStateNormal]; [button1121 addTarget:self action:@selector(button1121DidPush:) forControlEvents:UIControlEventTouchUpInside]; [button112 addSubview:button1121]; // 追加1-1-2-2按钮 UIButton* button1122 = [UIButton buttonWithType:UIButtonTypeRoun dedRect]; button1122.frame = CGRectMake(155,10,95,80); [button1122 setTitle:@”1-1-2-2” forState:UIControlStateNormal]; [button1122 addTarget:self action:@selector(button1122DidPush:) forControlEvents:UIControlEventTouchUpInside]; [button112 addSubview:button1122];
此段实例代码的执行结果如图2-10所示。
图2-10 addSubView:方法实例
另外,在UIView中还有superview属性及subviews属性。通过superview属性可以取得追加自己的UIView(父元素),而subviews可以以数组NSArray的形式取得追加到自己之下的所有UIView(子元素)。单击图2-10中的任意按钮,显示其父元素以及子元素列表的代码如下所示。以下实例代码是紧接着上面实例代码的。
-(void)button11DidPush:(id)sender { [self alertMessage:sender]; } -(void)button111DidPush:(id)sender { [self alertMessage:sender]; } -(void)button112DidPush:(id)sender { [self alertMessage:sender]; } -(void)button1121DidPush:(id)sender { [self alertMessage:sender]; } -(void)button1122DidPush:(id)sender { [self alertMessage:sender]; } -(void)alertMessage:(UIButton*)button { // 显示self的标题作为警告框的标题 NSString* title = [NSString stringWithFormat:@"self = %@",button.titleLabel.text]; // 取得superview的标题 // 但是当superview为非UIButton的情况下,以“UIViewController”替代 NSString* superViewName; if([button.superview isKindOfClass:[UIButton class]]){ superViewName =((UIButton*)button.superview).titleLabel.text; } else { superViewName = @"UIViewController"; } // 取得subviews的标题 NSMutableString* subviews = [[[NSMutableString alloc] initWithCapacity:64] autorelease]; [subviews setString:@""]; for(id view in button.subviews){ NSString* addString; if([view isKindOfClass:[UIButton class]]){ // 如果子元素为UIButton时,取titleLabel的text属性值 addString =((UIButton*)view).titleLabel.text; } else if([view isKindOfClass:[UILabel class]]){ // 如果为UILabel时取其text属性值 addString =((UILabel*)view).text; } else { // 上述以外的情况 addString = [view description]; } if([subviews length] > 0){ [subviews appendString:@","]; } [subviews appendString:addString]; } NSString* message = [NSString stringWithFormat:@"superview =%@\r\nsubviews = %@",superViewName,subviews]; UIAlertView* alert = [[[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:nil otherButtonTitles:@”OK”,nil ] autorelease]; [alert show];}
例如,当触摸[1-1-2]时,将显示如图2-11所示的警告框。
图2-11 显示superview与subviews的信息
此时,[1-1-2]的父元素为[1-1],子元素为[1-1-2]与[1-1-2-1]及[1-1-2-2]。之所以[1-1-2]会包含于其中而作为UIButton的子元素,是因为管理自身标题的UILabel也是其子元素之一。
2.3.2 子元素的插入与删除
上一小节我们介绍了如何使用addSubview:方法进行子元素的追加。实际上,追加子元素的方法除 addSubView:之外,还有insertSubview:atIndex:方法、insertSubview:aboveSubview:方法以及insertSubview:belowSubview:方法。另外,从父元素中删除特定的子元素时可使用removeFromSuperview:方法。
除上述方法外,用于管理UIView子元素状态的方法还有:交换两个子元素顺序的exchangeSubviewAtIndex:withSubviewAtIndex:方法以及检查是否为某元素的子元素的isDescendantOfView:方法。
上述六个方法使用实例代码如下所示。
// 追加父标签 parent_ = [[UILabel alloc] initWithFrame:CGRectMake(0,0,320,320)]; parent_.textAlignment = UITextAlignmentCenter; parent_.text = @"PARENT"; [self.view addSubview:parent_]; // 追加1个子标签 UILabel* child3 = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease]; child3.text = @"CHILD 3"; [child3 sizeToFit]; [parent_ insertSubview:child3 atIndex:0]; // 在上一个标签CHILD 3 下插入 CHILD 1 UILabel* child1 = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease]; child1.text = @"CHILD 1"; [child1 sizeToFit]; [parent_ insertSubview:child1 belowSubview:child3]; // 在CHILD 1 上追加 CHILD 2 UILabel* child2 = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease]; child2.text = @"CHILD 2"; [child2 sizeToFit]; [parent_ insertSubview:child2 aboveSubview:child1]; // 让CHILD 1 与 CHILD 3 交换 [parent_ exchangeSubviewAtIndex:0 withSubviewAtIndex:2]; // 如果CHILD 3 为 PARENT 子元素的话 if([child3 isDescendantOfView:parent_]){ // 删除CHILD 3 [child3 removeFromSuperview]; }
2.3.3 UIView的靠前显示与退后隐藏
多个UIView追加到同一画面上时,此时肯定会出现其中几个相互重叠的情况。这种情况下,我们可以调用bringSubviewToFront:方法将特定的UIView放置在前方,也可以调用sendSubviewToBack:方法将特定的UIView移动到后方。例如,我们在画面上追加了labelA_与labelB_两个标签,依次追加 labelA_与labelB_的代码如下。
[self.view addSubview:labelA_]; [self.view addSubview:labelB_];
画面显示的效果如图2-12所示。
图2-12 重叠的UIView
labelB_是后面追加进来的,因此labelB_必然是在前方显示。此时如果想让labelA_标签在前方显示,可以调用bringSubviewToFront:方法,代码如下。
[self.view bringSubviewToFront:labelA_];
执行后显示的效果如图2-13所示。
图2-13 将A标签置前
相反,如果我们再次想让labelA_移动到后方显示时,可调用sendSubviewToBack:方法,代码如下。
[self.view sendSubviewToBack:labelA_];
此时将画面返回如图2-13所示的状态。
2.3.4 附加标签(tag)及UIView的检索
UIView中定义有tag属性。在此tag属性中开发人员可以自行设置数值。但是就算设置了此属性值也不会影响程序本身的运行。tag属性通常只是被开发人员作为标记来使用。明确设置了tag属性的UIView可以使用viewWithTag:方法很简单地检索到,以下是tag属性的使用实例,注意此处仅罗列了主要的代码。
-(void)viewDidLoad { [super viewDidLoad]; // 背景设置成黑色 self.view.backgroundColor = [UIColor blackColor]; // 追加父标签 parent_ = [[UILabel alloc] initWithFrame:CGRectMake(0,0,320,320)]; parent_.textAlignment = UITextAlignmentCenter; parent_.text = @"PARENT"; [self.view addSubview:parent_]; // 追加10个子标签 for(int i = 1;i <= 10;++i){ UILabel* child = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease]; child.text = [NSString stringWithFormat:@"CHILD %d",i];[child sizeToFit]; CGPoint newPoint = child.center;newPoint.y += 30 * i; child.center = newPoint; [parent_ addSubview:child]; // 将第8个标签的tag设置成999 if(8 == i){ child.tag = 999; } } // 追加search按钮 UIButton* searchButton = [UIButton buttonWithType:UIButtonTypeRo undedRect]; searchButton.frame = CGRectMake(0,0,150,40); CGPoint newPoint = self.view.center; newPoint.y = self.view.frame.size.height - 40; searchButton.center = newPoint; [searchButton setTitle:@"search 999" forState:UIControlState Normal]; [searchButton addTarget:self action:@selector(searchDidPush) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:searchButton]; } #pragma mark ----- Private Methods ----- -(void)searchDidPush { NSString* message; // 从parent_的子元素中检索tag为999的元素,找到后显示警告框 UILabel* label =(UILabel*)[parent_ viewWithTag:999]; if(label){ message = label.text; } else { message = @"nothing"; } UIAlertView* alert = [[[UIAlertView alloc] initWithTitle:@"search 999" message:message delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK",nil ] autorelease]; [alert show]; }