34

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

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

11 回答 11

30

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

[cell.contentView addSubview:aView];

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

于 2010-05-20T17:27:39.217 回答
23

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

使用风险自负(此代码片段accessoryView向左移动任何 8 个像素。从所需子类[self positionAccessoryView];的方法内部调用):-(void)layoutSubviewsUITableViewCell

- (void)layoutSubviews {
    [super layoutSubviews];
    [self positionAccessoryView];
}

- (void)positionAccessoryView {
    UIView *accessory = nil;
    if (self.accessoryView) {
        accessory = self.accessoryView;
    } else if (self.accessoryType != UITableViewCellAccessoryNone) {
        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 isKindOfClass:[UIButton class]]) {
                accessory = subview;
                break;
            }
        }
    }

    CGRect r = accessory.frame;
    r.origin.x -= 8;
    accessory.frame = r;
}
于 2011-05-27T08:46:32.850 回答
16

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

CGRect adjustedFrame = self.accessoryView.frame;
adjustedFrame.origin.x += 10.0f;
self.accessoryView.frame = adjustedFrame;
于 2013-09-24T19:20:55.310 回答
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;
于 2014-01-15T13:22:56.510 回答
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;
            }
        }
    } 
}
于 2013-05-04T20:12:59.713 回答
2

也许这对你来说就足够了:

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;

通过这种方式,我在右侧添加了填充,因此附件按钮看起来向左移动。它具有更宽的区域来响应触摸,这是唯一的副作用。

于 2013-06-27T09:45:34.770 回答
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);
    }
}
于 2013-08-02T12:59:17.053 回答
2

为在任何单元格状态下持久化的附件视图设置自定义位置的简单方法是在 layoutSubViews 中布局附件视图:

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.accessoryView.center = CGPointMake($yourX, $yourY);
}
于 2017-03-16T13:28:46.597 回答
1

我正在使用 ios5,Alexey 给出的解决方案并没有完全奏效。我发现当在表上设置了附件类型时,附件视图为空,因此第一个“如果”不起作用。我稍微更改了代码:

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 中可以正常工作。

于 2012-08-14T12:07:04.667 回答
1

其他答案的改进

对于 James Kuang,KappeaccessoryView的默认附件视图为零。

对于 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
        }
    }
}
于 2017-08-11T02:18:46.210 回答
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
}
于 2020-03-20T20:07:28.753 回答