subview事件響應範圍

來源:互聯網
上載者:User

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

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

/*
// 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];

  運行可以看到如下介面:

  該例子中我們設定定製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事件。

  如果我們的程式有些時候看著一些按鈕明明正常但是卻不能正常接收touch訊息的時候,可能就是其顯示位置已經跑出了superview的frame範圍了。所以程式的rootview一定要時刻充滿整個window,否則就可能導致程式的某些地方不能正常相應使用者訊息。同時建議對於那些只是充當容器的view,最好設定autoresizingMask的值為UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight,這樣當其superview的大小發生變化時候就會自動縮放至superview一樣大小,保證每一刻都充滿其superview,從而避免因顯示位置出界導致的不能正常相應使用者touch事件等問題。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.