首页 > 代码库 > UIButton on UITableViewCell

UIButton on UITableViewCell

关于处于表视图行单元 contentView 中的 UIButton 短按不产生高亮效果的问题

在做demo时, 发现 UITableViewCell 中的 UIButton 短按一次看不到默认的变灰效果, 停留稍长才能变灰, 比如twitter官方客户端用户头像, 微博的转评赞三按钮。 微博各类客户端的头像和其他按钮也是这样, 头像很多直接是imageView加手势。 这方面细节处理的最好的是 Instagram 不管短按长按都会灰, 这样才有打击感。

经一番搜索之后得知 UITableView 做为 UIScrollView 的子类,拥有 delaysContentTouches 的布尔属性, 且默认为 YES, 即延迟响应 UIScrollView 子视图中的事件, 在这个短暂的延迟中, 如果触摸发生了移动, 则响应为滚动事件, 若没有移动且子视图中有 UIControl 类型且触摸位置处于该控件的话则被立即传递并触发相应事件。 所以当短按 UIButton 时, 先被系统判断为不是滚动事件才被传给子视图控件, 但高亮效果的动画被绕过了, 事件被直接传递。 所以只有当手指停留稍长时间时, 才度过了延迟时间从而看到了高亮效果。

若想要让 UIButton 短按长按均可显示高亮特效的话, 就是去掉这个延迟。 在你创建完表视图对象的地方, 或其初始化方法中加入以下代码, 将其默认的值改为 NO 。

1
someTableViewObject.delaysContentTouches = NO;

但这个时候又会发现, 当手指以 UIButton 区域做为滚动操作的起始点的话, UIScrollView就不响应滚动的手势动作了。

如果希望 UITableView 上的所有地方总能响应滚动事件的话, 就需要子类化 UITableView并重写其从父类 UIScrollView 继承来的如下方法了

1234567
// default returns YES if view isn‘t a UIControl// Returns whether to cancel touches related to the content subview and start dragging.- (BOOL)touchesShouldCancelInContentView:(UIView *)view{    // 即使触摸到的是一个 UIControl (如子类:UIButton), 我们也希望拖动时能取消掉动作以便响应滚动动作    return YES;}

通过 UIScrollView 头文件中的注释, 以及苹果官方文档的说明可以得知, 因为其默认如果事件在 UIControl 或其子类响应时, 返回为 NO, 即 即使触摸发生移动, 也不响应为滚动事件。 所以让其始终返回 YES, 即 UIScrollView 在屏幕上显示的任何位置的触摸事件, 如果发生移动, 均可响应为滚动事件。

** iOS 7 中的处理

123456789
// 在初始化 Cell 的地方for (id view in self.subviews) {    if ([NSStringFromClass([view class]) isEqualToString:@"UITableViewCellScrollView"]) {        UIScrollView *scrollView = (UIScrollView *) view;        scrollView.delaysContentTouches = NO;        break;    }}

** iOS 8 中还要增加的处理

1234567891011
// 在初始化 TableView 的地地方for (id view in self.subviews) {    if ([NSStringFromClass([view class]) isEqualToString:@"UITableViewCellScrollView"]) {        if([view isKindOfClass:[UIScrollView class]])        {            UIScrollView *scrollView = (UIScrollView *) view;            scrollView.delaysContentTouches = NO;        }        break;    }}

UIButton on UITableViewCell