代码之家  ›  专栏  ›  技术社区  ›  anon

为UITableViewCell的AccessoryView使用自定义图像并使其响应UITableViewDelegate

  •  138
  • anon  · 技术社区  · 15 年前

    我正在使用一个自定义绘制的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次)未被触发。代表肯定是正确地连接起来的。

    可能缺少什么?

    谢谢大家。

    9 回复  |  直到 10 年前
        1
  •  228
  •   Jim Dovey    15 年前

    遗憾的是,除非您使用某个预定义类型时提供的内部按钮类型被点击,否则不会调用该方法。要使用自己的,您必须将附件创建为按钮或其他uicontrol子类(我建议使用 -buttonWithType:UIButtonTypeCustom 以及设置按钮的图像,而不是使用uiImageView)。

    这里有一些我在前哨站中使用的东西,它定制了足够多的标准小部件(只是稍微,以匹配我们的青色),我最后做了自己的uitableviewcontroller中介子类来保存所有其他表视图要使用的实用程序代码(它们现在子类optableviewcontroller)。

    首先,此函数使用自定义图形返回一个新的详细信息披露按钮:

    - (UIButton *) makeDetailDisclosureButton
    {
        UIButton * button = [UIButton outpostDetailDisclosureButton];
    
    [button addTarget: self
                   action: @selector(accessoryButtonTapped:withEvent:)
         forControlEvents: UIControlEventTouchUpInside];
    
        return ( 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];
    }
    

    此函数通过从按钮提供的事件中获取触摸的表视图中的位置并向表视图询问该点的行索引路径来定位行。

        2
  •  77
  •   NANNAV gngrwzrd    11 年前

    我发现这个网站非常有用: custom accessory view for your uitableview in iphone

    简而言之,在 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];
        }
    }
    
        3
  •  7
  •   yanchenko    12 年前

    我的方法是创建一个 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
    
        4
  •  3
  •   Zaggo    11 年前

    以上是对Jim Dovey答案的扩展:

    使用uiSearchBarController和uiTableView时要小心。在这种情况下,你要检查 self.searchDisplayController.active 使用 self.searchDisplayController.searchResultsTableView 而不是 self.tableView . 否则,当SearchDisplayController处于活动状态时,尤其是当搜索结果滚动时,您将得到意外的结果。

    例如:

    - (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];
    }
    
        5
  •  2
  •   Míng    12 年前
    1. 为按钮的标记定义宏:

      #define AccessoryViewTagSinceValue 100000 // (AccessoryViewTagSinceValue * sections + rows) must be LE NSIntegerMax
      
    2. 创建单元格时,创建按钮并设置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方法-TableView:CellForRowatindexPath中的indexPath设置cell.accessoryView.tag:

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

      - (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.
      }
      
        6
  •  2
  •   Eric Welander    11 年前

    当点击按钮时,可以让它在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]];
    
     }
    
        7
  •  1
  •   Toydor    12 年前

    对于Yanchenko方法,我不得不补充: [accBtn setFrame:CGRectMake(0, 0, 20, 20)];

    如果使用XIB文件自定义TableCell,那么将不会调用initWithStyle:ReuseIdentifier:

    替代替代:

    -(void)awakeFromNib
    {
    //Put your code here 
    
    [super awakeFromNib];
    
    }
    
        8
  •  1
  •   Divyu    11 年前

    必须使用 UIControl 正确获取事件调度(例如 UIButton )而不是简单的 UIView/UIImageView .

        9
  •  0
  •   aeu    10 年前

    从iOS 3.2开始,您可以避免其他人推荐的按钮,而是使用带有点击手势识别器的uiImageView。请确保启用用户交互,这在uiImageView中是默认关闭的。