iOS開(kāi)發(fā)中Subview的事件響應(yīng)以及獲取subview的方法
Subview的事件響應(yīng)
在view的層級(jí)里面,默認(rèn)情況下subview是可以顯示到其父view的frame區(qū)域以外的,通過(guò)設(shè)置clipToBounds屬性為YES,可以限制subview的顯示區(qū)域。但是touch在各個(gè)UIView中傳遞的時(shí)候,區(qū)域時(shí)限制在view的frame內(nèi),此處包含兩個(gè)信息:1、在當(dāng)前view的frame以外所做的操作是不會(huì)傳遞到該view中的,這一點(diǎn)很容易理解。2、如果touch事件是發(fā)生在當(dāng)前view的frame以外,該view所有的subview將也不會(huì)再收到該消息。這一點(diǎn)通常容易被我們忽略,很多奇怪的問(wèn)題就是這個(gè)引起的。
下面請(qǐng)看一個(gè)小例子,定制view的代碼如下:
SvTestClipSubviewEvent.h
//
// SvTestClipSubviewEvent.h
// SvUIViewSample
//
// Created by maple on 3/19/12.
// Copyright (c) 2012 smileEvday. All rights reserved.
//
// 默認(rèn)的情況下,subView可以超出父view的frame,即可以顯示到父View的外邊
// 但是消息的接受返回卻是由于父View的大小限制,即出了父View的subView將不能收到消息
// 在程序中一定要注意當(dāng)前程序view的最底層是充滿整個(gè)window的可用區(qū)域的,
// 否則將會(huì)導(dǎo)致某些區(qū)域明明有按鈕但是卻點(diǎn)不中的問(wèn)題
#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中添加如下測(cè)試代碼:
SvTestClipSubviewEvent *testClipSubView = [[SvTestClipSubviewEvent alloc]initWithFrame:CGRectMake(100, 100, 150, 150)];
[self.view addSubview:testClipSubView];
[testClipSubView release];
運(yùn)行可以看到如下界面:

獲取subview
通常我們?cè)趘iew層級(jí)里面對(duì)subView的操作可以通過(guò)兩種方式:1、保留一個(gè)subview的引用,然后在類(lèi)中通過(guò)該引用對(duì)該subview進(jìn)行操作,但是要注意在適當(dāng)?shù)奈恢锰砑觾?nèi)存維護(hù)的代碼,退出前手動(dòng)釋放。2、設(shè)置subview的Tag,讓后在要使用的時(shí)候,通過(guò)viewWithTag獲取到相應(yīng)的subview,這種方法比較簡(jiǎn)潔,也不用自己去維護(hù)內(nèi)存。
ViewWithTag: 通常采用深度遍歷優(yōu)先的算法,返回第一個(gè)tag和給定Tag相等的subview。這就導(dǎo)致了一個(gè)當(dāng)一個(gè)view的多個(gè)subview的tag相同的時(shí)候,我們通過(guò)該方法得到的view可能并不是自己想要的。
下面通過(guò)一個(gè)小例子驗(yàn)證一下,代碼如下:
//
// SvTestViewTag.h
// SvUIViewSample
//
// Created by maple on 3/18/12.
// Copyright (c) 2012 smileEvday. All rights reserved.
//
// view根據(jù)Tag獲取subView的時(shí)候執(zhí)行的是深度優(yōu)先遍歷的算法
// 返回第一個(gè)Tag和請(qǐng)求tag相等的子View
// 從subViews中查找,最下層的優(yōu)先找到
#import <UIKit/UIKit.h>
@interface SvTestViewWithTag : UIView
@end

例子中每個(gè)subview都是一個(gè)UILabel,而且設(shè)置了相應(yīng)的內(nèi)容。按鈕的響應(yīng)函數(shù)的實(shí)現(xiàn)思路:首先隱藏所有類(lèi)型為UILabel的subview(排除UIButton,因?yàn)閎utton需要一直顯示),然后根據(jù)指定的Tag獲取到相應(yīng)的subview,該subview及其superView的hidden屬性為NO。這樣就可以保證點(diǎn)擊按鈕的時(shí)候只顯示的是第一個(gè)tag和指定tag相等的subview。
為了驗(yàn)證viewWithTag獲取subview的原理:
首先我在subview1中添加了兩個(gè)tag都為11的subview11和subview12。 運(yùn)行程序可以,當(dāng)我們點(diǎn)擊"Show Tag 11"按鈕的時(shí)候屏幕上將顯示“SubView11”,而非“SubView12”。同時(shí)不管你點(diǎn)擊幾次該按鈕,始終只顯示“SubView11”。這樣可以看出來(lái)同一層級(jí)中獲取subview時(shí)候查找順序?yàn)閕ndex從小到大的原則,即位于相對(duì)下層的將首先被找到。
其次我還在subview1中添加了tag均為13的subview13,同時(shí)向view中添加了tag也為13的subview2,運(yùn)行程序點(diǎn)擊“Show Tag 13”按鈕,屏幕上將會(huì)顯示“SubView13”,而非“SubView2”。這可以驗(yàn)證viewWithTag在搜索的時(shí)候遵循深度優(yōu)先遍歷的原則,即會(huì)首先查找最下層的view并遞歸查詢其subview。
綜上兩點(diǎn)我們可以看出來(lái)viewWithTag獲取subview的基本原則,即遵循深度優(yōu)先,下層優(yōu)先兩個(gè)原則。
- iOS開(kāi)發(fā)中的ViewController轉(zhuǎn)場(chǎng)切換效果實(shí)現(xiàn)簡(jiǎn)介
- iOS開(kāi)發(fā)中ViewController的頁(yè)面跳轉(zhuǎn)和彈出模態(tài)
- iOS9 系統(tǒng)分享調(diào)用之UIActivityViewController
- 詳解iOS開(kāi)發(fā)中UIPickerView控件的使用方法
- iOS開(kāi)發(fā)中WebView的基本使用方法簡(jiǎn)介
- 詳解iOS開(kāi)發(fā)中的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)和組動(dòng)畫(huà)以及UIView封裝動(dòng)畫(huà)
- iOS開(kāi)發(fā)中使用UIScrollView實(shí)現(xiàn)圖片輪播和點(diǎn)擊加載
- iOS開(kāi)發(fā)中UITableview控件的基本使用及性能優(yōu)化方法
- 詳解iOS開(kāi)發(fā)中UItableview控件的數(shù)據(jù)刷新功能的實(shí)現(xiàn)
- IOS如何使用CAShapeLayer實(shí)現(xiàn)復(fù)雜的View的遮罩效果
相關(guān)文章
iOS開(kāi)發(fā)中Subview的事件響應(yīng)以及獲取subview的方法
這篇文章主要介紹了iOS開(kāi)發(fā)中Subview的事件響應(yīng)以及獲取subview的方法,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-09-09
Flutter?GetPageRoute實(shí)現(xiàn)嵌套導(dǎo)航學(xué)習(xí)
這篇文章主要為大家介紹了Flutter?GetPageRoute實(shí)現(xiàn)嵌套導(dǎo)航的示例學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
iOS中實(shí)現(xiàn)簡(jiǎn)單易懂秒殺倒計(jì)時(shí)/倒計(jì)時(shí)代碼
這篇文章主要介紹了iOS中實(shí)現(xiàn)簡(jiǎn)單易懂秒殺倒計(jì)時(shí)/倒計(jì)時(shí)代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02

