Subview的事件响应
在view的层级里面,默认情况下subview是可以显示到其父view的frame区域以外的,通过设置clipToBounds属性为YES,可以限制subview的显示区域。但是touch在各个UIView中传递的时候,区域时限制在view的frame内,此处包含两个信息:1、在当前view的frame以外所做的操作是不会传递到该view中的,这一点很容易理解。2、如果touch事件是发生在当前view的frame以外,该view所有的subview将也不会再收到该消息。这一点通常容易被我们忽略,很多奇怪的问题就是这个引起的。 下面请看一个小例子,定制view的代码如下: 复制代码 代码如下: SvTestClipSubviewEvent.h //// SvTestClipSubviewEvent.h
// SvUIViewSample
//
// Created by maple on 3/19/12.
// Copyright (c) 2012 smileEvday. All rights reserved.
//
// 默认的情况下,subView可以超出父view的frame,即可以显示到父View的外边
// 但是消息的接受返回却是由于父View的大小限制,即出了父View的subView将不能收到消息
// 在程序中一定要注意当前程序view的最底层是充满整个window的可用区域的,
// 否则将会导致某些区域明明有按钮但是却点不中的问题
#import <UIKit/UIKit.h>
@interface SvTestClipSubviewEvent : UIView
@end
复制代码 代码如下:
// // SvTestClipSubviewEvent.m // SvUIViewSample // // Created by maple on 3/19/12. // Copyright (c) 2012 smileEvday. All rights reserved. //#import "SvTestClipSubviewEvent.h"
@interface SvTestClipSubviewEvent()
- (void)btnAction:(UIButton*)btn;
@end
@implementation SvTestClipSubviewEvent
- (id)initWithFrame:(CGRect)frame
{ self = [super initWithFrame:frame]; if (self) { // Initialization code self.backgroundColor = [UIColor redColor]; UIButton *testOutBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; testOutBtn.frame = CGRectMake(-80, -50, 70, 30); [testOutBtn addTarget:self action:@selecto (btnAction: forControlEvents:UIControlEventTouchUpInside]; [testOutBtn setTitle:@"I'm out" forState:UIControlStateNormal]; [self addSubview:testOutBtn]; UIButton *testInBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; testInBtn.frame = CGRectMake(20, 30, 70, 30); [testInBtn setTitle:@"I'm in" forState:UIControlStateNormal]; [testInBtn addTarget:self action:@selector(btnAction: forControlEvents:UIControlEventTouchUpInside]; [self addSubview:testInBtn]; } return self; } /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */- (void)btnAction:(UIButton*)sender
{ NSLog(@"HI, you tap button %@", [sender titleForState:UIControlStateNormal]); } @end 在程序的ViewController中添加如下测试代码: 复制代码 代码如下: SvTestClipSubviewEvent *testClipSubView = [[SvTestClipSubviewEvent alloc]initWithFrame:CGRectMake(100, 100, 150, 150)]; [self.view addSubview:testClipSubView]; [testClipSubView release]; 运行可以看到如下界面:获取subview
通常我们在view层级里面对subView的操作可以通过两种方式:1、保留一个subview的引用,然后在类中通过该引用对该subview进行操作,但是要注意在适当的位置添加内存维护的代码,退出前手动释放。2、设置subview的Tag,让后在要使用的时候,通过viewWithTag获取到相应的subview,这种方法比较简洁,也不用自己去维护内存。 ViewWithTag: 通常采用深度遍历优先的算法,返回第一个tag和给定Tag相等的subview。这就导致了一个当一个view的多个subview的tag相同的时候,我们通过该方法得到的view可能并不是自己想要的。 下面通过一个小例子验证一下,代码如下: 复制代码 代码如下: // // SvTestViewTag.h // SvUIViewSample // // Created by maple on 3/18/12. // Copyright (c) 2012 smileEvday. All rights reserved. // // view根据Tag获取subView的时候执行的是深度优先遍历的算法 // 返回第一个Tag和请求tag相等的子View // 从subViews中查找,最下层的优先找到#import <UIKit/UIKit.h>
@interface SvTestViewWithTag : UIView
@end
精彩评论