我們知道當多個視圖進行疊加的時候,touch事件是作用到最上面的視圖上,但是如果父視圖是UIScrollView,如果預設,可能touch子視圖會造成UIScrollView的滾動。
UIScrollView滾動的原因,可以看UIScrollView 原理。
我在這裡簡單的描述一下,UIScrollView的工作原理,當手指touch的時候,UIScrollView會攔截Event,會等待一段時間,在這段時間內,如果沒有手指沒有移動,當時間結束時,UIScrollView會發送tracking events到子視圖上。在時間結束前,手指發生了移動,那麼UIScrollView就會進行移動,從而取笑發送tracking。
那麼,UIScrollView的子類想要接受touch事件,就是使用者點擊UIScrollView上的視圖時,要先處理視圖上的touch,而不發生滾動。這時候就需要UIScrollView的子類重載touchesShouldBegin:withEvent:inContentView: ,從而決定自己是否接受子視圖中的touch事件。
上面都是理論的知識,下面看一個簡單的例子:
外面紅色是一個UIScrollView,黃色是在UIScrollView上添加的UIView。最後的效果是,當在黃色地區內touch時,touch事件會作用到UIView上,當touch紅色地區時,整個視圖上下滾動。下面是實現的過程。
一、建立工程,然後建立myScrollView,並且myScrollView繼承自UIScrollView。
#import <UIKit/UIKit.h>
@interface myScrollView : UIScrollView {
}
@end
具體的實現:
#import "myScrollView.h"
#import "MyView.h"
@implementation myScrollView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setBackgroundColor:[UIColor redColor]];
MyView *myView=[[MyView alloc] initWithFrame:CGRectMake(1, 3, 100, 200)];
[self addSubview:myView];
[myView release];
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
NSLog(@"使用者點擊了scroll上的視圖%@,是否開始滾動scroll",view);
//返回yes 是不滾動 scroll 返回no 是滾動scroll
return YES;
}
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
NSLog(@"使用者點擊的視圖 %@",view);
//NO scroll不可以滾動 YES scroll可以滾動
return NO;
}
@end
重寫了- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view方法和- (BOOL)touchesShouldCancelInContentView:(UIView *)view方法。
其中(BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view,是使用者點擊黃色地區內,先觸發這個方法,當返回YES時,touch事件作用到黃色視圖上,當返回no時,紅色可以上下滾動。
(BOOL)touchesShouldCancelInContentView:(UIView *)view是發送tracking前,先作用這個方法。
下面是點擊黃的地區的日誌:
2011-06-02 10:19:42.469 scrollTouch[38255:207] 使用者點擊了scroll上的視圖<MyView: 0x4e26f90; frame = (1 3; 100 200); layer = <CALayer: 0x4e270a0>>,是否開始滾動scroll
2011-06-02 10:19:42.658 scrollTouch[38255:207] 使用者點擊的視圖 <MyView: 0x4e26f90; frame = (1 3; 100 200); layer = <CALayer: 0x4e270a0>>
二、添加mySrollView到根視圖上:
- (void)viewDidLoad
{
[super viewDidLoad];
myScrollView *view=[[myScrollView alloc] initWithFrame:CGRectMake(10, 9, 300, 400)];
[view setUserInteractionEnabled:YES];
[view setScrollEnabled:YES];
//NO 發送滾動的通知 但是就算手指移動 scroll也不會動了 YES 發送通知 scroll可以移動
[view setCanCancelContentTouches:YES];
[view setBounces:NO];
// NO 立即通知touchesShouldBegin:withEvent:inContentView 看是否滾動 scroll
[view setDelaysContentTouches:NO]; // 這句是關鍵,預設為YES,不設為NO則touchesShouldBegin:withEvent:inContentView:可能不被回調
[view setContentSize:CGSizeMake(300, 900)];
[self.view addSubview:view];
[view release];
}
三、MyView視圖的實現。
#import "MyView.h"
@implementation MyView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setBackgroundColor:[UIColor yellowColor]];
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
@end
原始碼:http://easymorse-iphone.googlecode.com/svn/trunk/scrollTouch/