UITableViewCell自定义重新排序控件

时间:2010-08-23 11:45:08

标签: iphone cocoa-touch uitableview ios4

有没有办法更改UITableView处于编辑模式时显示的重新排序控件的图像?我有一个UIImage,我想显示而不是通常的灰色条。

我是否必须继承UITableViewCell才能完成此任务?

6 个答案:

答案 0 :(得分:9)

我想你现在还有很长的路要走,但这已经出现了一个新的问题。

请在此处查看我的回答:

Change default icon for moving cells in UITableView

答案 1 :(得分:4)

我最近遇到了为重新排序控件更改图像的需要,因为我将UITableViewCell子类化以提供我自己的自定义表格单元格。作为这项工作的一部分,我将单元格的背景更改为默认颜色以外的其他内容。

一切正常,但当我将UITableView置于编辑模式时,将出现重新排序控件,带有白色背景 - 而不是我用于单元格的背景颜色。这看起来并不好,我希望背景匹配。

在各种版本的iOS中,UITableViewCell中的视图层次结构已发生变化。我采用的方法将遍历整个视图集,直到找到UITableViewCellReorderControl私有类。我相信这将适用于iOS 5和所有后续iOS版本的答案。请注意,虽然UITableViewCellReorderControl类本身是私有的,但我没有使用任何私有API来查找它。

首先,这里是扫描重新排序控制的代码;我假设文本"重新排序"将成为班级名称 - 苹果未来可能会改变:

-(UIView *) findReorderView:(UIView *) view
{
    UIView *reorderView = nil;
    for (UIView *subview in view.subviews)
    {
        if ([[[subview class] description] rangeOfString:@"Reorder"].location != NSNotFound)
        {
            reorderView = subview;
            break;
        }
        else
        {
            reorderView = [self findReorderView:subview];
            if (reorderView != nil)
            {
                break;
            }
        }
    }
    return reorderView;
}

在自定义UITableViewCell子类中,您将覆盖-(void) setEditing:animated:并在此处查找重新排序控件。如果在表未处于编辑模式时尝试查找此控件,则重新排序控件将不在该单元的视图层次结构中:

-(void) setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing:editing animated:animated];
    if (editing)
    {
        // find the reorder view here
        // place the previous method either directly in your
        // subclassed UITableViewCell, or in a category
        // defined on UIView
        UIView *reorderView = [self findReorderView:self];
        if (reorderView)
        {
            // here, I am changing the background color to match my custom cell
            // you may not want or need to do this
            reorderView.backgroundColor = self.contentView.backgroundColor;
            // now scan the reorder control's subviews for the reorder image
            for (UIView *sv in reorderView.subviews)
            {
                if ([sv isKindOfClass:[UIImageView class]])
                {
                    // and replace the image with one that you want
                    ((UIImageView *)sv).image = [UIImage imageNamed:@"yourImage.png"];
                    // it may be necessary to properly size the image's frame
                    // for your new image - in my experience, this was necessary
                    // the upper left position of the UIImageView's frame
                    // does not seem to matter - the parent reorder control
                    // will center it properly for you
                    sv.frame = CGRectMake(0, 0, 48.0, 48.0);
                }
            }
        }
    }
}

您的里程可能会有所不同;我希望这适合你。

答案 2 :(得分:2)

这是我基于Rick Morgan的答案的Swift解决方案:

&&

效果很好。 func adjustSize() { // we're trying to leverage the existing reordering controls, however that means the table must be kept in editing mode, // which shrinks the content area to less than full width to make room for editing controls let cellBounds = bounds let contentFrame = contentView.convert(contentView.bounds, to: self) let leftPadding = contentFrame.minX - cellBounds.minX let rightPadding = cellBounds.maxX - contentFrame.maxX // adjust actual content so that it still covers the full length of the cell contentLeadingEdge.constant = -leftPadding // this should pull our custom reorder button in line with the system button contentTrailingEdge.constant = -rightPadding // make sure we can still see and interact with the content that overhangs contentView.clipsToBounds = false // recursive search of the view tree for a reorder control func findReorderControl(_ view: UIView) -> UIView? { // this is depending on a private API, retest on every new iPad OS version if String(describing: type(of: view)).contains("Reorder") { return view } for subview in view.subviews { if let v = findReorderControl(subview) { return v } } return nil } // hunt down the system reorder button and make it invisible but still operable findReorderControl(self)?.alpha = 0.05 // don't go too close to alpha 0, or it will be considered hidden } contentLeadingEdge是我在Interface Builder中在contentTrailingEdge和实际内容之间设置的布局约束。我的代码从contentView委托方法中调用了adjustSize方法。

但是,最终,我接受了克利夫顿的建议,即只涉及重新订购控制。我将UIImageView直接添加到tableView(_:, willDisplay:, forRowAt:)的单元格中(而不是contentView),将其定位,并且在调用awakeFromNib时,我只是将图像视图置于最前面,并涵盖了重新排序无需依赖任何私有API即可进行控制。

答案 3 :(得分:1)

我最近做了一些工作,但是很短暂。我尝试设置自己的editingAccesoryView但无法让reorder控件更改。奇。

我的猜测是它与UITableviewCell文档中的以下注释有关: showsReorderControl

  

如果值为YES,则重新排序   控制暂时取代任何   配件视图。

换句话说,editAccessoryView正在被重新排序的控件视图取代,这可能就是我们无法覆盖重新排序控件的原因。希望有人能找到解决方法。

答案 4 :(得分:0)

也许我们都在过度思考这个问题。 :)

只需将自定义UIImageView放在默认移动附件的顶部,即可覆盖它。完成。

答案 5 :(得分:-1)

将单元格的editingAccessoryView属性设置为包含所需图像的图像视图。

顺便说一句,我会提醒你在做这件事时要小心。当您将自定义图形替换为系统标准(例如重新排序图形)时,您将面临混淆用户的严重风险。标准UI语法告诉他们在重新排序时需要标准图形,他们可能不了解自定义图形的重要性。