为UITableViewCell的accessoryView使用自定义图像并让它响应UITableViewDelegate

138 cocoa-touch uitableview uikit ios

我正在使用自定义绘制的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];
Run Code Online (Sandbox Code Playgroud)

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

self.userInteractionEnabled = YES;
Run Code Online (Sandbox Code Playgroud)

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

可能会遗漏什么?

谢谢大家.

Jim*_*vey 228

遗憾的是,除非使用其中一种预定义类型时提供的内部按钮类型被轻敲,否则不会调用该方法.要使用你自己的,你必须创建你的配件作为一个按钮或其他UIControl子类(我建议使用-buttonWithType:UIButtonTypeCustom和设置按钮的图像按钮,而不是使用UIImageView).

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

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

- (UIButton *) makeDetailDisclosureButton
{
    UIButton * button = [UIButton outpostDetailDisclosureButton];

[button addTarget: self
               action: @selector(accessoryButtonTapped:withEvent:)
     forControlEvents: UIControlEventTouchUpInside];

    return ( button );
}
Run Code Online (Sandbox Code Playgroud)

该按钮将在完成后调用此例程,然后为附件按钮提供标准的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];
}
Run Code Online (Sandbox Code Playgroud)

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

  • 只是对于其他人来看这个答案,你也可以在按钮上放一个标签对应行(如果你有多个部分,你需要做一些数学运算),然后只需从标签中拉出标签功能.我认为它可能比计算触摸快一点. (11认同)
  • @RyanJM我曾经认为做一个hitTest是矫枉过正的,标签就足够了.事实上我在我的一些代码中使用了标签的想法.但是今天我遇到了用户可以添加新行的问题.这会使用标签杀死黑客.Jim Dovey提出的解决方案(以及Apple的示例代码中所示)是一种通用解决方案,适用于所有情况 (4认同)
  • 这需要你对`self.tableView`进行硬编码.如果您不知道哪个tableview包含该行怎么办? (3认同)

Jon*_*Jon 77

我发现这个网站非常有用: 在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;
Run Code Online (Sandbox Code Playgroud)

然后,实现此方法:

- (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];
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我会说+1,因为这是Apple建议他们在他们的文档中的示例代码中做的事情:http://developer.apple.com/library/ios/#samplecode/Accessory/Listings/MyTableViewController_m.html#//apple_ref/DOC/UID/DTS40008066-MyTableViewController_m-DontLinkElementID_6 (4认同)

yan*_*nko 7

我的方法是创建一个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
Run Code Online (Sandbox Code Playgroud)