我看过很多关于类似事情的帖子,但没有一个匹配或解决这个问题。从iOS 7开始,每当我将UIButton
添加到UITableViewCell
或甚至添加到页脚视图时,它都会“正常”,这意味着它会收到目标操作,但它不显示通常会发生的小亮点当您点按UIButton
时。这使得UI看起来很时髦而没有显示按钮对触摸的反应。
我很确定这是iOS7中的一个错误,但是有人找到了解决方案或者可以帮我找到一个:)
编辑: 我忘了提到它会突出显示我是否长按按钮,但不会像刚刚添加到标准视图那样快速点击。
代码:
创建按钮:
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.titleLabel.font = [UIFont systemFontOfSize:14];
button.titleLabel.textColor = [UIColor blueColor];
[button setTitle:@"Testing" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonPressed:) forControlEvents: UIControlEventTouchDown];
button.frame = CGRectMake(0, 0, self.view.frame.size.width/2, 40);
我测试过的事情:
//删除UITableView
上的手势识别器,以防他们挡路。
for (UIGestureRecognizer *recognizer in self.tableView.gestureRecognizers) {
recognizer.enabled = NO;
}
//从Cell中删除手势
for (UIGestureRecognizer *recognizer in self.contentView.gestureRecognizers) {
recognizer.enabled = NO;
}
//这显示了轻微的触摸,但这不是理想的外观
button.showsTouchWhenHighlighted = YES;
答案 0 :(得分:87)
在该表视图中,您只需添加此属性。
tableview.delaysContentTouches = NO;
在启动单元格后添加cellForRowAtIndexPath,只需添加以下代码即可。在iOS 6和iOS 7中,单元的结构明显不同 iOS 7我们在UITableViewCell和内容View之间有一个控件UITableViewCellScrollView。
for (id obj in cell.subviews)
{
if ([NSStringFromClass([obj class]) isEqualToString:@"UITableViewCellScrollView"])
{
UIScrollView *scroll = (UIScrollView *) obj;
scroll.delaysContentTouches = NO;
break;
}
}
答案 1 :(得分:40)
从iOS 8开始,我们需要将相同的技术应用于UITableView子视图(表包含隐藏的UITableViewWrapperView滚动视图)。不再需要迭代UITableViewCell子视图。
for (UIView *currentView in tableView.subviews) {
if ([currentView isKindOfClass:[UIScrollView class]]) {
((UIScrollView *)currentView).delaysContentTouches = NO;
break;
}
}
This answer应与此问题相关联。
答案 2 :(得分:27)
我试图将此添加到已接受的答案中,但它从未经历过。这是关闭单元delayedContentTouches属性的一种更安全的方法,因为它不查找特定的类,而是查找响应选择器的任何内容。
在细胞中:
for (id obj in self.subviews) {
if ([obj respondsToSelector:@selector(setDelaysContentTouches:)]) {
[obj setDelaysContentTouches:NO];
}
}
在TableView中:
self.tableView.delaysContentTouches = NO;
答案 3 :(得分:18)
对于适用于iOS7和iOS8的解决方案,请创建自定义UITableView
子类和自定义UITableViewCell
子类。
使用此示例UITableView
' s initWithFrame:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// iterate over all the UITableView's subviews
for (id view in self.subviews)
{
// looking for a UITableViewWrapperView
if ([NSStringFromClass([view class]) isEqualToString:@"UITableViewWrapperView"])
{
// this test is necessary for safety and because a "UITableViewWrapperView" is NOT a UIScrollView in iOS7
if([view isKindOfClass:[UIScrollView class]])
{
// turn OFF delaysContentTouches in the hidden subview
UIScrollView *scroll = (UIScrollView *) view;
scroll.delaysContentTouches = NO;
}
break;
}
}
}
return self;
}
使用此示例UITableViewCell
' s initWithStyle:reuseIdentifier:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// iterate over all the UITableViewCell's subviews
for (id view in self.subviews)
{
// looking for a UITableViewCellScrollView
if ([NSStringFromClass([view class]) isEqualToString:@"UITableViewCellScrollView"])
{
// this test is here for safety only, also there is no UITableViewCellScrollView in iOS8
if([view isKindOfClass:[UIScrollView class]])
{
// turn OFF delaysContentTouches in the hidden subview
UIScrollView *scroll = (UIScrollView *) view;
scroll.delaysContentTouches = NO;
}
break;
}
}
}
return self;
}
答案 4 :(得分:16)
我为解决问题所做的是使用以下代码的一类UIButton:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
[NSOperationQueue.mainQueue addOperationWithBlock:^{ self.highlighted = YES; }];
}
- (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
[self performSelector:@selector(setDefault) withObject:nil afterDelay:0.1];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
[self performSelector:@selector(setDefault) withObject:nil afterDelay:0.1];
}
- (void)setDefault
{
[NSOperationQueue.mainQueue addOperationWithBlock:^{ self.highlighted = NO; }];
}
当我在UITableViewCell中按下按钮时,按钮会正确反应,而我的UITableView正常运行,因为delaysContentTouches
不是强制的。
答案 5 :(得分:10)
这是罗曼B在Swift 2中的答案:
URL in address bar Effective URL
------------------ -------------
sub.projdomain.com sub.projdomain.com/myapp/default/index
sub.projdomain.com/ sub.projdomain.com/myapp/default/index
sub.projdomain.com/foo sub.projdomain.com/myapp/foo/index
sub.projdomain.com/foo?p=1 sub.projdomain.com/myapp/foo/index?p=1
sub.projdomain.com/foo/?p=2 sub.projdomain.com/myapp/foo/index?p=2
sub.projdomain.com/foo/bar?p=3 sub.projdomain.com/myapp/foo/bar?p=3
sub.projdomain.com/foo/bar/?p=4 sub.projdomain.com/myapp/foo/bar?p=4
sub.projdomain.com/a sub.projdomain.com/admin/default/site
答案 6 :(得分:5)
- (void)viewDidLoad
{
[super viewDidLoad];
for (id view in self.tableView.subviews)
{
// looking for a UITableViewWrapperView
if ([NSStringFromClass([view class]) isEqualToString:@"UITableViewWrapperView"])
{
// this test is necessary for safety and because a "UITableViewWrapperView" is NOT a UIScrollView in iOS7
if([view isKindOfClass:[UIScrollView class]])
{
// turn OFF delaysContentTouches in the hidden subview
UIScrollView *scroll = (UIScrollView *) view;
scroll.delaysContentTouches = NO;
}
break;
}
}
}
答案 7 :(得分:4)
这是RaphaëlPinto上面回答的 Swift 版本。不要忘记向他投票:)
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
super.touchesBegan(touches, withEvent: event)
NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in self.highlighted = true }
}
override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {
super.touchesCancelled(touches, withEvent: event)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_main_queue()) {
self.setDefault()
}
}
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
super.touchesEnded(touches, withEvent: event)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_main_queue()) {
self.setDefault()
}
}
func setDefault() {
NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in self.highlighted = false }
}
答案 8 :(得分:4)
我在UITableViewCell中遇到与纯文本UIButton类似的问题,而不是在触摸时突出显示。为我修复的是将buttonType从Custom更改回System。
将delaysContentTouches设置为NO对同一UITableViewCell中仅图像的UIButton设置了技巧。
self.tableView.delaysContentTouches = NO;
答案 9 :(得分:3)
仅限iOS8的Swift解决方案(需要为iOS7的每个单元格进行额外的工作):
//
// NoDelayTableView.swift
// DivineBiblePhone
//
// Created by Chris Hulbert on 30/03/2015.
// Copyright (c) 2015 Chris Hulbert. All rights reserved.
//
// This solves the delayed-tap issue on buttons on cells.
import UIKit
class NoDelayTableView: UITableView {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
delaysContentTouches = false
// This solves the iOS8 delayed-tap issue.
// http://stackoverflow.com/questions/19256996/uibutton-not-showing-highlight-on-tap-in-ios7
for view in subviews {
if let scroll = view as? UIScrollView {
scroll.delaysContentTouches = false
}
}
}
override func touchesShouldCancelInContentView(view: UIView!) -> Bool {
// So that if you tap and drag, it cancels the tap.
return true
}
}
要使用,您所要做的就是将故事板中的班级更改为NoDelayTableView
。
我可以确认,在iOS8中,放置在单元格内的contentView内的按钮现在可以立即突出显示。
答案 10 :(得分:2)
Chris Harrison's answer的略微修改版本。 Swift 2.3:
class HighlightButton: UIButton {
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
super.touchesBegan(touches, withEvent: event)
NSOperationQueue.mainQueue().addOperationWithBlock { _ in self.highlighted = true }
}
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
super.touchesCancelled(touches, withEvent: event)
setDefault()
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
super.touchesEnded(touches, withEvent: event)
setDefault()
}
private func setDefault() {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
NSOperationQueue.mainQueue().addOperationWithBlock { _ in self.highlighted = false }
}
}
}
答案 11 :(得分:1)
对于我来说,接受的答案对某些“轻拍”并不起作用。
最后,我在一个uibutton类别(/ subclass)中添加了波纹管代码,它可以百分之百地工作。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.backgroundColor = [UIColor greenColor];
[UIView animateWithDuration:0.05 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.backgroundColor = [UIColor clearColor];
} completion:^(BOOL finished)
{
}];
[super touchesBegan:touches withEvent:event];
}
答案 12 :(得分:0)
由于objc是动态的,而scrollView是唯一响应delayedContentTouches的类,这应该适用于ios 7和8(将它放在tableViewController的早期,比如awakeFromNib):
for (id view in self.tableView.subviews)
{
if ([view respondsToSelector:@selector(delaysContentTouches)]) {
UIScrollView *scrollView = (UIScrollView *)view;
scrollView.delaysContentTouches = NO;
break;
}
}
您可能还必须通过选择viewController中的表来关闭storyboard或nib中的“delaysContentTouches”。顺便说一下,如果你在viewController中使用tableView,这可能不适用于ios 7,至少我无法让它工作。
答案 13 :(得分:0)
对我来说这个解决方案不起作用,我修复继承TableView并实现这两个方法
- (instancetype)initWithCoder:(NSCoder *)coder{
self = [super initWithCoder:coder];
if (self) {
for (id obj in self.subviews) {
if ([obj respondsToSelector:@selector(setDelaysContentTouches:)]){
[obj performSelector:@selector(setDelaysContentTouches:) withObject:NO];
}
}
}
return self;
}
- (BOOL)delaysContentTouches{
return NO;
}
答案 14 :(得分:0)
适用于iOS 7和8的Swift解决方案:
首先我写了一个实用函数:
class func classNameAsString(obj: AnyObject) -> String {
return _stdlib_getDemangledTypeName(obj).componentsSeparatedByString(".").last!
}
然后我继承UITableView并实现它:
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
for view in self.subviews {
if (Utility.classNameAsString(view) == "UITableViewWrapperView") {
if view.isKindOfClass(UIScrollView) {
var scroll = (view as UIScrollView)
scroll.delaysContentTouches = false
}
break
}
}
}
我也是UITableViewCell的子类并实现它:
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
for view in self.subviews {
if (Utility.classNameAsString(view) == "UITableViewCellScrollView") {
if view.isKindOfClass(UIScrollView) {
var scroll = (view as UIScrollView)
scroll.delaysContentTouches = false
}
}
}
}
在我的情况下,init(编码器:)将运行。请将调试点放在init函数中以了解将运行哪个init函数,然后使用上面的代码使其工作。 希望能帮助别人。
答案 15 :(得分:0)
我在UITableViewCell
上写了一个类别扩展名,以简化此问题。除了我从UITableViewCell contentView
向上走视图层次结构(而不是向下)之外,它与接受的答案基本相同。
我认为这是一个完全“自动化”的解决方案,可以让添加到UITableView
的所有单元格设置为delaysContentTouches
状态,以匹配拥有UITableView
的{{1}}状态。为了完成这项工作,我必须调动delaysContentTouches
,或要求开发人员使用UITableView
子类。我不想要求我解决这个我觉得更简单,更灵活的解决方案。
此处的类别扩展和示例工具:
https://github.com/TomSwift/UITableViewCell-TS_delaysContentTouches
使用起来很简单:
UITableView
以下是该类别的代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// using static cells from storyboard...
UITableViewCell* cell = [super tableView: tableView cellForRowAtIndexPath: indexPath];
cell.ts_delaysContentTouches = NO;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
答案 16 :(得分:0)
在Swift 3中,这个UIView扩展可以在UITableViewCell上使用。最好采用cellForRowAt
方法。
func removeTouchDelayForSubviews() {
for subview in subviews {
if let scrollView = subview as? UIScrollView {
scrollView.delaysContentTouches = false
} else {
subview.removeTouchDelayForSubviews()
}
}
}