在view的层级里面,默认情况下subview是可以显示到其父view的frame区域以外的,通过设置clipToBounds属性为YES,可以限制subview的显示区域。但是touch在各个UIView中传递的时候,区域时限制在view的frame内,此处包含两个信息:1、在当前view的frame以外所做的操作是不会传递到该view中的,这一点很容易理解。2、如果touch事件是发生在当前view的frame以外,该view所有的subview将也不会再收到该消息。这一点通常容易被我们忽略,很多奇怪的问题就是这个引起的。

  下面请看一个小例子,定制view的代码如下:



//
//  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 

@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:@selector(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;

}




- (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的事件响应_touch事件

  该例子中我们设置定制view的背景颜色为红色,然后创建一个位于定制view外的UIButton “I'm out”以及另一个位于定制view内的UIButton “I‘m in”。运行程序,我们可以发现点击"I'm out"按钮时界面根本没有变化,在btnAction:函数中加断点,也不会进去,这就说明该按钮根本没有接受到消息,同时“I'm in”按钮运行正常,点击后控制台会输出信息“...UIViewSample[664:f803] HI, you tap button I'm in”。这些可以说明subview接收事件的范围是受其superview的frame闲限制的,不可能接受到superview的frame以外的touch事件。

leWidth| UIViewAutoresizingFlexibleHeight,这样当其superview的大小发生变化时候就会自动缩放至superview一样大小,保证每一刻都充满其superview,从而避免因显示位置出界导致的不能正常相应用户touch事件等问题。