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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2876041/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:15:54  来源:igfitidea点击:

Can a standard accessory view be in a different position within a UITableViewCell?

iosobjective-ciphoneuitableviewaccessoryview

提问by cannyboy

I want my accessory to be in a slightly different place than normal. Is it possible? This code has no effect:

我希望我的配件与正常位置略有不同。是否可以?这段代码没有效果:

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

采纳答案by rickharrison

No, you cannot move where the accessory view is. As an alternative you can add a subview like the following;

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

[cell.contentView addSubview:aView];

Also, by setting the accessoryViewproperty equal to something, the accessoryTypevalue is ignored.

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

回答by Alexey

There is a way to move default accessoryView, but it's pretty hacky. So it might stop working one day when a new SDK arrives.

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

Use at your own risk (this code snippet moves any accessoryView8 pixels to the left. Call [self positionAccessoryView];from inside the -(void)layoutSubviewsmethod of the desired UITableViewCellsubclass):

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

- (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;
}

回答by James Kuang

I was able to change the accessory view's frame by simply doing this in my custom cell subclass.

只需在我的自定义单元子类中执行此操作,我就能够更改附件视图的框架。

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

回答by Ole

Another way to do this is to embed your custom accessory view in another view, that is set as the cell's accessory view and control the padding using the frame.

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

Here is an example with an image view as custom accessory view:

这是一个图像视图作为自定义附件视图的示例:

// 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;

回答by Kappe

The simple way to set a custom positionfor the accessoryViewthat is persisted in any cell statusis to layout the accessoryView in layoutSubViews:

最简单的方法来设置自定义位置accessoryView的在任何细胞状态持续是布局accessoryView的在layoutSubViews:

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

回答by Tomasz

Following the solution given by Ana I tried to better detect the accessory view, I look on the right side of the cell.

按照 Ana 给出的解决方案,我试图更好地检测附件视图,我查看了单元格的右侧。

Create a custom class that extends UITableViewCell and add this method:

创建一个扩展 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;
            }
        }
    } 
}

回答by ancajic

Maybe this will be sufficient for you:

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

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;

This way I added padding to the right, so accessory button looks shifted to the left. It has a wider area that responds to touches, that is the only side-effect.

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

回答by larshaeuser

The above answers didn't work for me under ios 6.1. So I tried to use UIEdgeInsets, because the DetailDisclosure is a UIButton. And it works fine now. Here the source:

以上答案在 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);
    }
}

回答by C?ur

improvements on other answers

其他答案的改进

For James Kuang, Kappe, accessoryViewis nil for default accessory view.

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

For Matjan, subviews.lastObjectis easily the wrong view, like an UITableViewCellSeparatorView.

对于 Matjan 来说,subviews.lastObject很容易是错误的视图,比如 UITableViewCellSeparatorView。

For Alexey, Ana, Tomasz, enumerating the subviews until we find an unknown one works for now. But it's laborious and could be easily broken in future versions if, let say, Apple adds a backgroundAccessoryView.

对于 Alexey、Ana、Tomasz,枚举子视图直到我们找到一个未知的子视图。但是它很费力,并且在未来的版本中很容易被破坏,比如 Apple 添加一个backgroundAccessoryView.

For larshaeuser, enumerating the subviews until we find a UIButton is good idea, but contentEdgeInsetsis not adequately visibly changing the accessory view.

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

solution for Swift 3.x and 4.0

Swift 3.x 和 4.0 的解决方案

We will enumerate and look for the last UIButton.

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

class AccessoryTableViewCell: UITableViewCell {
    override func layoutSubviews() {
        super.layoutSubviews()
        if let lastButton = subviews.reversed().lazy.flatMap({ 
class AccessoryTableViewCell: UITableViewCell {
    override func layoutSubviews() {
        super.layoutSubviews()
        // https://stackoverflow.com/a/45625959/1033581
        if let lastButton = subviews.reversed().lazy.compactMap({ 
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;

}
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 } } }
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 } } }

for Swift 4.1 and newer

适用于 Swift 4.1 及更新版本

##代码##

回答by Ana

I was working with the ios5 and the solution given by Alexey was not working entirely. I discovered that when an accessoryType is set on a table, the accessoryView is null so the first "if" was not working. I have changed a the code just a little:

我正在使用 ios5,而 Alexey 给出的解决方案并不完全有效。我发现当在表上设置了一个附件类型时,附件视图是空的,所以第一个“如果”不起作用。我对代码做了一点改动:

##代码##

and this solution is working for me. As Alexey said, I don't know what is going to happen with future versions but at least in ios 4 is working.

这个解决方案对我有用。正如阿列克谢所说,我不知道未来版本会发生什么,但至少在 ios 4 中是有效的。