对UITableViewCell的accessoryView使用自定义图像,并使其响应UITableViewDelegate

我正在使用一个自定义绘制的UITableViewCell,包括单元的accessoryView相同。 我的设置为accessoryView发生像这样的事情:

 UIImage *accessoryImage = [UIImage imageNamed:@"accessoryDisclosure.png"]; UIImageView *accImageView = [[UIImageView alloc] initWithImage:accessoryImage]; accImageView.userInteractionEnabled = YES; [accImageView setFrame:CGRectMake(0, 0, 28.0, 28.0)]; self.accessoryView = accImageView; [accImageView release]; 

另外,当单元格初始化时,使用initWithFrame:reuseIdentifier:我确保设置以下属性:

 self.userInteractionEnabled = YES; 

不幸的是在我的UITableViewDelegate中,我的tableView:accessoryButtonTappedForRowWithIndexPath:方法(尝试重复10次)没有被触发。 代表确实连线正确。

什么可能会丢失?

谢谢大家。

可悲的是,该方法不会被调用,除非你使用一个预定义的types提供的内部buttontypes被点击。 要使用自己的,你必须创build你的配件作为一个button或其他UIControl子类(我推荐一个button使用-buttonWithType:UIButtonTypeCustom和设置button的图像,而不是使用UIImageView)。

这里有一些我在Outpost中使用的东西,它定制了足够的标准小部件(只是略微,以匹配我们的蓝绿色),我做了我自己的UITableViewController中介子类,以保存所有其他表视图使用的实用程序代码(他们现在子类OPTableViewController)。

首先,这个函数使用我们的自定义graphics返回一个新的细节披露button:

 - (UIButton *) makeDetailDisclosureButton { UIButton * button = [UIButton outpostDetailDisclosureButton]; [button addTarget: self action: @selector(accessoryButtonTapped:withEvent:) forControlEvents: UIControlEventTouchUpInside]; return ( button ); } 

button将在完成时调用此例程,然后为附件button提供标准的UITableViewDelegate例程:

 - (void) accessoryButtonTapped: (UIControl *) button withEvent: (UIEvent *) event { NSIndexPath * indexPath = [self.tableView indexPathForRowAtPoint: [[[event touchesForView: button] anyObject] locationInView: self.tableView]]; if ( indexPath == nil ) return; [self.tableView.delegate tableView: self.tableView accessoryButtonTappedForRowWithIndexPath: indexPath]; } 

此函数通过从button提供的事件中获取触摸的表视图中的位置并向表视图索取该点处行的索引path来查找行。

我发现这个网站是非常有用的: 在iphone中为您的uitableview定制配件视图

总之,在cellForRowAtIndexPath:使用这个:

 UIImage *image = (checked) ? [UIImage imageNamed:@"checked.png"] : [UIImage imageNamed:@"unchecked.png"]; UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; CGRect frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height); button.frame = frame; [button setBackgroundImage:image forState:UIControlStateNormal]; [button addTarget:self action:@selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside]; button.backgroundColor = [UIColor clearColor]; cell.accessoryView = button; 

那么,执行这个方法:

 - (void)checkButtonTapped:(id)sender event:(id)event { NSSet *touches = [event allTouches]; UITouch *touch = [touches anyObject]; CGPoint currentTouchPosition = [touch locationInView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition]; if (indexPath != nil) { [self tableView: self.tableView accessoryButtonTappedForRowWithIndexPath: indexPath]; } } 

我的方法是创build一个UITableViewCell子类,并封装将在其中调用通常的UITableViewDelegate方法的逻辑。

 // CustomTableViewCell.h @interface CustomTableViewCell : UITableViewCell - (id)initForIdentifier:(NSString *)reuseIdentifier; @end // CustomTableViewCell.m @implementation CustomTableViewCell - (id)initForIdentifier:(NSString *)reuseIdentifier; { // the subclass specifies style itself self = [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier]; if (self) { // get the button elsewhere UIButton *accBtn = [ViewFactory createTableViewCellDisclosureButton]; [accBtn addTarget: self action: @selector(accessoryButtonTapped:withEvent:) forControlEvents: UIControlEventTouchUpInside]; self.accessoryView = accBtn; } return self; } #pragma mark - private - (void)accessoryButtonTapped:(UIControl *)button withEvent:(UIEvent *)event { UITableViewCell *cell = (UITableViewCell*)button.superview; UITableView *tableView = (UITableView*)cell.superview; NSIndexPath *indexPath = [tableView indexPathForCell:cell]; [tableView.delegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; } @end 

对Jim Dovey的回答如下:

在UITableView中使用UISearchBarController时要小心。 在这种情况下,你想检查self.searchDisplayController.active和使用self.searchDisplayController.searchResultsTableView而不是self.tableView 。 否则,当searchDisplayController处于活动状态时,特别是在滚动search结果时,会得到意想不到的结果。

例如:

 - (void) accessoryButtonTapped:(UIControl *)button withEvent:(UIEvent *)event { UITableView* tableView = self.tableView; if(self.searchDisplayController.active) tableView = self.searchDisplayController.searchResultsTableView; NSIndexPath * indexPath = [tableView indexPathForRowAtPoint:[[[event touchesForView:button] anyObject] locationInView:tableView]]; if(indexPath) [tableView.delegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; } 
  1. 为button标签定义一个macros:

     #define AccessoryViewTagSinceValue 100000 // (AccessoryViewTagSinceValue * sections + rows) must be LE NSIntegerMax 
  2. 创buildbutton并在创build单元格时设置cell.accessoryView

     UIButton *accessoryButton = [UIButton buttonWithType:UIButtonTypeContactAdd]; accessoryButton.frame = CGRectMake(0, 0, 30, 30); [accessoryButton addTarget:self action:@selector(accessoryButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; cell.accessoryView = accessoryButton; 
  3. 在UITableViewDataSource方法中通过indexPath设置cell.accessoryView.tag -tableView:cellForRowAtIndexPath:

     cell.accessoryView.tag = indexPath.section * AccessoryViewTagSinceValue + indexPath.row; 
  4. button的事件处理程序

     - (void) accessoryButtonTapped:(UIButton *)button { NSIndexPath *indexPath = [NSIndexPath indexPathForRow:button.tag % AccessoryViewTagSinceValue inSection:button.tag / AccessoryViewTagSinceValue]; [self.tableView.delegate tableView:self.tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; } 
  5. 实现UITableViewDelegate方法

     - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { // do sth. } 

当button被轻敲时,你可以在UITableViewCell子类中调用下面的方法

  -(void)buttonTapped{ // perform an UI updates for cell // grab the table view and notify it using the delegate UITableView *tableView = (UITableView *)self.superview; [tableView.delegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:[tableView indexPathForCell:self]]; } 

用yanchenko方法,我不得不添加: [accBtn setFrame:CGRectMake(0, 0, 20, 20)];

如果你使用xib文件来定制你的tableCell,那么initWithStyle:reuseIdentifier:不会被调用。

替代覆盖:

 -(void)awakeFromNib { //Put your code here [super awakeFromNib]; } 

您必须使用UIControl来正确获取事件分派(例如UIButton )而不是简单的UIView/UIImageView

从iOS 3.2开始,您可以避免使用其他人推荐的button,而是使用带有轻击手势识别器的UIImageView。 一定要启用用户交互,UIImageViews默认closures。