最近做項(xiàng)目的時(shí)候發(fā)現(xiàn),UIScrollView上的UIButton點(diǎn)擊的時(shí)候沒(méi)有高亮狀態(tài)坝冕,但是確實(shí)觸發(fā)了點(diǎn)擊事件欢峰,不過(guò)這樣會(huì)造成一個(gè)假象,給用戶看來(lái)UIButton沒(méi)有被點(diǎn)擊的感覺(jué)坑夯。 但是要是長(zhǎng)時(shí)間點(diǎn)擊的話岖寞,則會(huì)高亮。于是我發(fā)現(xiàn)柜蜈,導(dǎo)致這種現(xiàn)象應(yīng)該就是時(shí)間長(zhǎng)短的問(wèn)題仗谆。順著這個(gè)問(wèn)題想下去,就追尋到UIScrollView的touch原理淑履,UIScrollView有一個(gè)delaysContentTouches的屬性隶垮。
蘋(píng)果官方的文檔解釋?zhuān)篸efault is YES. if NO, we immediately call -touchesShouldBegin:withEvent:inContentView:. this has no effect on presses
很明顯,delaysContentTouches 默認(rèn)值為YES鳖谈,即UIScrollView會(huì)在接受到手勢(shì)是延遲150ms來(lái)判斷該手勢(shì)是否能觸發(fā)UIScrollView的滑動(dòng)事件岁疼;反之值為NO時(shí),UIScrollView會(huì)立馬將接受到的手勢(shì)分發(fā)到子視圖上缆娃。
當(dāng)然捷绒,delaysContentTouches設(shè)置為NO是遠(yuǎn)遠(yuǎn)不夠的,因?yàn)檫@樣的話你想要拖動(dòng)UIScrollView而七點(diǎn)落在替他有手勢(shì)識(shí)別的視圖上是會(huì)拖不動(dòng)的贯要。 于是我們要重載touchesShouldCancelInContentView暖侨,此方法決定手勢(shì)是否取消傳遞到View上,拖動(dòng)UIScrollView是觸發(fā)崇渗。返回NO時(shí)字逗,拖動(dòng)手勢(shì)將留在UIScrollView上;返回YES時(shí)宅广,則傳到View上葫掉。
現(xiàn)在,方案就很明確了跟狱,我們只要將UIButton所有屬于UIScrollView的父視圖的delaysContentTouches屬性設(shè)置成為NO且重寫(xiě)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相比更加復(fù)雜些
UITableView:
在iOS7和iOS8中的視圖結(jié)構(gòu)是不同的驶臊,且存在著很多我們?cè)诰幋a時(shí)永遠(yuǎn)接觸不到的視圖挪挤,但我們可通過(guò)Debug將其subviews逐個(gè)逐個(gè)找出來(lái)叼丑。這關(guān)系到我們這個(gè)問(wèn)題坑比較深的層次。
iOS7:UITableView中存在n+1個(gè)UIScrollView扛门,一個(gè)是UITableView本身鸠信,另外n個(gè)村在于UITableViewCell月cell的contenView之間,類(lèi)名為UITableVieCellScrollVIew论寨,在iOS8已經(jīng)移除星立。
iOS8:UITableView中存在2個(gè)UIScrollView,一個(gè)是UITableView本身葬凳,另外一個(gè)存在于UITableView與UITableViewCell之間贞铣,類(lèi)名為UITableViewWrapperView。需要注意的是沮明,UITableViewWrapperView在iOS7中并不是一個(gè)UIScrollView。
理解后直接貼代碼
@implementation ResponseTableView
- (instancetype) initWithCoder : (NSCoder *) aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.delaysContentTouches = NO;
//因?yàn)?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延遲高亮的方法.