标准附件视图可以在UITableViewCell内的不同位置吗?

时间:2010-05-20 16:57:48

标签: ios objective-c iphone uitableview accessoryview

我希望我的配件与正常情况略有不同。可能吗? 此代码无效:

cell.accessoryType =  UITableViewCellAccessoryDisclosureIndicator;
cell.accessoryView.frame = CGRectMake(5.0, 5.0, 5.0, 5.0);

11 个答案:

答案 0 :(得分:26)

不,你不能移动配件视图的位置。作为替代方案,您可以添加如下的子视图;

[cell.contentView addSubview:aView];

此外,通过将accessoryView属性设置为等于某个值,将忽略accessoryType值。

答案 1 :(得分:20)

有一种方法可以移动默认的accessoryView,但它非常hacky。因此,当新SDK到达时,它可能会停止工作一天。

使用风险由您自己承担(此代码段向左移动任意accessoryView 8个像素。将其插入所需-(void)layoutSubviews子类的UITableViewCell方法内:

if (self.accessoryView) {
    r = self.accessoryView.frame;
    r.origin.x -= 8;
    self.accessoryView.frame = r;
} else {
    UIView *defaultAccessoryView = nil;
    for (UIView *subview in self.subviews) {
        if (subview != self.textLabel && 
            subview != self.detailTextLabel && 
            subview != self.backgroundView && 
            subview != self.contentView &&
            subview != self.selectedBackgroundView &&
            subview != self.imageView) {
            defaultAccessoryView = subview;
            break;
        }
    }

    r = defaultAccessoryView.frame;
    r.origin.x -= 8;
    defaultAccessoryView.frame = r;
}

答案 2 :(得分:15)

我可以通过在我的自定义单元子类中执行此操作来更改附件视图的框架。

CGRect adjustedFrame = self.accessoryView.frame;
adjustedFrame.origin.x += 10.0f;
self.accessoryView.frame = adjustedFrame;

答案 3 :(得分:3)

另一种方法是将自定义配件视图嵌入到另一个视图中,该视图设置为单元格的附件视图并使用框架控制填充。

以下是将图像视图作为自定义附件视图的示例:

// Use insets to define the padding on each side within the wrapper view
UIEdgeInsets insets = UIEdgeInsetsMake(24, 0, 0, 0);

// Create custom accessory view, in this case an image view
UIImage *customImage = [UIImage imageNamed:@"customImage.png"];
UIImageView *accessoryView = [[UIImageView alloc] initWithImage:customImage];

// Create wrapper view with size that takes the insets into account 
UIView *accessoryWrapperView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, customImage.size.width+insets.left+insets.right, customImage.size.height+insets.top+insets.bottom)];

// Add custom accessory view into wrapper view
[accessoryWrapperView addSubview:accessoryView];

// Use inset's left and top values to position the custom accessory view inside the wrapper view
accessoryView.frame = CGRectMake(insets.left, insets.top, customImage.size.width, customImage.size.height);

// Set accessory view of cell (in this case this code is called from within the cell)
self.accessoryView = accessoryWrapperView;

答案 4 :(得分:2)

根据Ana给出的解决方案,我试图更好地检测附件视图,我看着单元格的右侧。

创建一个扩展UITableViewCell的自定义类并添加此方法:

- (void)layoutSubviews {
    [super layoutSubviews];

    if (self.accessoryType != UITableViewCellAccessoryNone) {
        float estimatedAccesoryX = MAX(self.textLabel.frame.origin.x + self.textLabel.frame.size.width, self.detailTextLabel.frame.origin.x + self.detailTextLabel.frame.size.width);

        for (UIView *subview in self.subviews) {
            if (subview != self.textLabel &&
                subview != self.detailTextLabel &&
                subview != self.backgroundView &&
                subview != self.contentView &&
                subview != self.selectedBackgroundView &&
                subview != self.imageView &&
                subview.frame.origin.x > estimatedAccesoryX) {

                // This subview should be the accessory view, change its frame
                frame = subview.frame;
                frame.origin.x -= 10;
                subview.frame = frame;
                break;
            }
        }
    } 
}

答案 5 :(得分:2)

上述答案在ios 6.1下对我不起作用。所以我尝试使用UIEdgeInsets,因为DetailDisclosure是一个UIButton。它现在工作正常。来源:

if (cell.accessoryType == UITableViewCellAccessoryDetailDisclosureButton) {
    UIView* defaultAccessoryView = [cell.subviews lastObject];
    if ([defaultAccessoryView isKindOfClass:[UIButton class]]){
        UIButton *bt = (UIButton*)defaultAccessoryView;            
        bt.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 10);
    }
}

答案 6 :(得分:2)

附件视图设置自定义位置的简单方法是在任何单元格状态中保持,这是在layoutSubViews中布局accessoryView:

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.accessoryView.center = CGPointMake($yourX, $yourY);
}

答案 7 :(得分:1)

我正在使用ios5,Alexey提供的解决方案并不完全正常。我发现当在表上设置一个accessoryType时,accessoryView为null,因此第一个“if”不起作用。我已经改变了一些代码:

if (self.accessoryType != UITableViewCellAccessoryNone) {
    UIView* defaultAccessoryView = nil;

    for (UIView* subview in self.subviews) {
        if (subview != self.textLabel && 
            subview != self.detailTextLabel && 
            subview != self.backgroundView && 
            subview != self.contentView &&
            subview != self.selectedBackgroundView &&
            subview != self.imageView &&
            subview != self.explanationButton && // Own button
            subview.frame.origin.x > 0 // Assumption: the checkmark will always have an x position over 0. 
            ) {
            defaultAccessoryView = subview;
            break;
        }
    }
    r = defaultAccessoryView.frame;
    r.origin.x -= 8;
    defaultAccessoryView.frame = r;

}

这个解决方案对我有用。正如Alexey所说,我不知道未来版本会发生什么,但至少在ios 4中工作正在发挥作用。

答案 8 :(得分:1)

也许这对你来说已经足够了:

UIImageView* accessoryImageView = [[UIImageView alloc] initWithFrame:
        CGRectMake(0, 0, accessoryImage.size.width + MARGIN_RIGHT, accessoryImage.size.height)];
accessoryImageView.contentMode = UIViewContentModeLeft;
accessoryImageView.image = accessoryImage;

self.accessoryView = accessoryImageView;

这样我向右添加了填充,因此附件按钮看起来向左移动。它有更广泛的区域响应触摸,这是唯一的副作用。

答案 9 :(得分:1)

其他答案的改进

对于James Kuang,Kappe,accessoryView默认配件视图为零。

对于Matjan,subviews.lastObject很容易出错,就像UITableViewCellSeparatorView一样。

对于Alexey,Ana,Tomasz,列举子视图,直到找到一个未知的子视图现在可以工作。但是,如果Apple添加了backgroundAccessoryView,那么它在将来的版本中很容易被破坏。

对于larshaeuser,在我们找到UIButton之前枚举子视图是个好主意,但是contentEdgeInsets并没有充分明显地改变附件视图。

Swift 3.x和4.0

的解决方案

我们将枚举并查找最后一个UIButton。

class AccessoryTableViewCell: UITableViewCell {
    override func layoutSubviews() {
        super.layoutSubviews()
        if let lastButton = subviews.reversed().lazy.flatMap({ $0 as? UIButton }).first {
            // This subview should be the accessory view, change its origin
            lastButton.frame.origin.x = bounds.size.width - lastButton.frame.size.width - 5
        }
    }
}

适用于Swift 4.1和更新版

class AccessoryTableViewCell: UITableViewCell {
    override func layoutSubviews() {
        super.layoutSubviews()
        // https://stackoverflow.com/a/45625959/1033581
        if let lastButton = subviews.reversed().lazy.compactMap({ $0 as? UIButton }).first {
            // This subview should be the accessory view, change its origin
            lastButton.frame.origin.x = bounds.size.width - lastButton.frame.size.width - 5
        }
    }
}

答案 10 :(得分:0)

这是我所使用的,它将摆脱默认的填充。

override func layoutSubviews() {
    super.layoutSubviews()

    // Remove the accessory view's default padding.
    accessoryView!.frame.origin.x = bounds.width - accessoryView!.bounds.width - safeAreaInsets.right
    contentView.frame.size.width = bounds.width - safeAreaInsets.left - safeAreaInsets.right - accessoryView!.bounds.width
}