原文地址:http://www.jianshu.com/p/b4331f06bd34
最近做項目的時候發現,UIScrollView上的UIButton點擊的時候沒有高亮狀態,但是確實觸發了點擊事件,不過這樣會造成一個假象,給用戶看來UIButton沒有被點擊的感覺。 但是要是長時間點擊的話,則會高亮。於是我發現,導致這種現象應該就是時間長短的問題。順著這個問題想下去,就追尋到UIScrollView的touch原理,UIScrollView有一個delaysContentTouches的屬性。蘋果官方的文檔解釋:default is YES. if NO, we immediately call -touchesShouldBegin:withEvent:inContentView:. this has no effect on presses
很明顯,delaysContentTouches 默認值為YES,即UIScrollView會在接受到手勢是延遲150ms來判斷該手勢是否能觸發UIScrollView的滑動事件;反之值為NO時,UIScrollView會立馬將接受到的手勢分發到子視圖上。
當然,delaysContentTouches設置為NO是遠遠不夠的,因為這樣的話你想要拖動UIScrollView而七點落在替他有手勢識別的視圖上是會拖不動的。 於是我們要重載touchesShouldCancelInContentView,此方法決定手勢是否取消傳遞到View上,拖動UIScrollView是觸發。返回NO時,拖動手勢將留在UIScrollView上;返回YES時,則傳到View上。
現在,方案就很明確了,我們只要將UIButton所有屬於UIScrollView的父視圖的delaysContentTouches屬性設置成為NO且重寫touchesShouldCancelInContentView方法就行。下面直接貼代碼
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self.delaysContentTouches = NO;
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.delaysContentTouches = NO;
}
return self;
}
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
if ([view isKindOfClass:[UIButton class]]) {
return YES;
}
return [super touchesShouldCancelInContentView:view];
}
這就是UIScrollView的讓UIButton高亮方法,然而UITableview相比更加復雜些
UITableView:
在iOS7和iOS8中的視圖結構是不同的,且存在著很多我們在編碼時永遠接觸不到的視圖,但我們可通過Debug將其subviews逐個逐個找出來。這關系到我們這個問題坑比較深的層次。
iOS7:UITableView中存在n+1個UIScrollView,一個是UITableView本身,另外n個村在於UITableViewCell月cell的contenView之間,類名為UITableVieCellScrollVIew,在iOS8已經移除。
iOS8:UITableView中存在2個UIScrollView,一個是UITableView本身,另外一個存在於UITableView與UITableViewCell之間,類名為UITableViewWrapperView。需要注意的是,UITableViewWrapperView在iOS7中並不是一個UIScrollView。
理解後直接貼代碼
@implementation ResponseTableView
- (instancetype) initWithCoder : (NSCoder *) aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.delaysContentTouches = NO;
//因為 UITableViewWrapperView 在iOS7不屬於UIScrollView
//iOS7
for (id obj in self.subviews) {
if ([NSStringFromClass([obj class]) isEqualToString:@"UITableViewCellScrollView"]) {
UIScrollView *scrollView = (UIScrollView *) obj;
scrollView.delaysContentTouches = NO;
break;
}
}
//ios 8
for (id view in self.subviews) {
if ([NSStringFromClass([view class]) isEqualToString:@"UITableViewWrapperView"]) {
if ([view isKindOfClass:[UIScrollView class]]) {
UIScrollView *scrollView = (UIScrollView *) view;
scrollView.delaysContentTouches = NO;
}
break;
}
}
}
return self;
}
- (BOOL) touchesShouldCancelInContentView : (UIView *) view {
if ([view isKindOfClass:[UIButton class]]) {
return YES;
}
return [super touchesShouldCancelInContentView:view];
}
以上,就能解決Button延遲高亮的方法.