在UITableView中更改移动单元格的默认图标

时间:2011-12-22 11:38:48

标签: ios uitableview

我需要在UITableView中更改移动单元格的默认图标。

这一个:

enter image description here

有可能吗?

11 个答案:

答案 0 :(得分:53)

这是一个真正的hacky解决方案,可能无法长期运作,但可能会给你一个起点。重新订购控件是UITableViewCellReorderControl,但这是私有类,因此您无法直接访问它。但是,您可以查看子视图的层次结构并找到其imageView。

您可以通过继承UITableViewCell并覆盖其setEditing:animated:方法来执行此操作,如下所示:

- (void) setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing: editing animated: YES];

    if (editing) {

        for (UIView * view in self.subviews) {
            if ([NSStringFromClass([view class]) rangeOfString: @"Reorder"].location != NSNotFound) {
                for (UIView * subview in view.subviews) {
                    if ([subview isKindOfClass: [UIImageView class]]) {
                        ((UIImageView *)subview).image = [UIImage imageNamed: @"yourimage.png"];
                    }
                }
            }
        }
    }   
}

或者在Swift中

override func setEditing(_ editing: Bool, animated: Bool) {
    super.setEditing(editing, animated: animated)

    if editing {
        for view in subviews where view.description.contains("Reorder") {
            for case let subview as UIImageView in view.subviews {
                subview.image = UIImage(named: "yourimage.png")
            }
        }
    }
}

请注意......这可能不是一个长期解决方案,因为Apple可以随时更改视图层次结构。

答案 1 :(得分:13)

Ashley Mills'答案在提供时非常出色,但正如其他人在评论中所指出的那样,视图层次结构已从iOS版本更改为版本。为了正确地找到重新排序控件,我使用遍历整个视图层次结构的方法;希望这将使该方法有机会继续工作,即使Apple更改了视图层次结构。

这是我用来查找重新订购控件的代码:

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

以下是我用来覆盖子类中-(void) setEditing:animated:方法的代码:

-(void) setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing:editing animated:animated];
    if (editing)
    {
        // I'm assuming the findReorderView method noted above is either
        // in the code for your subclassed UITableViewCell, or defined
        // in a category for UIView somewhere
        UIView *reorderView = [self findReorderView:self];
        if (reorderView)
        {
            // I'm setting the background color of the control
            // to match my cell's background color
            // you might need to do this if you override the
            // default background color for the cell
            reorderView.backgroundColor = self.contentView.backgroundColor;
            for (UIView *sv in reorderView.subviews)
            {
                // now we find the UIImageView for the reorder control
                if ([sv isKindOfClass:[UIImageView class]])
                {
                    // and replace it with the image we want
                    ((UIImageView *)sv).image = [UIImage imageNamed:@"yourImage.png"];
                    // note:  I have had to manually change the image's frame
                    // size to get it to display correctly
                    // also, for me the origin of the frame doesn't seem to
                    // matter, because the reorder control will center it
                    sv.frame = CGRectMake(0, 0, 48.0, 48.0);
                }
            }
        }
    }
}

答案 2 :(得分:6)

Swift 版本的Rick的答案几乎没有改进:

override func setEditing(editing: Bool, animated: Bool) {
    super.setEditing(editing, animated: animated)

    if editing {
        if let reorderView = findReorderViewInView(self), 
            imageView = reorderView.subviews.filter({ $0 is UIImageView }).first as? UIImageView {
            imageView.image = UIImage(named: "yourImage")
        }
    }
}

func findReorderViewInView(view: UIView) -> UIView? {
    for subview in view.subviews {
        if String(subview).rangeOfString("Reorder") != nil {
            return subview
        }
        else {
            findReorderViewInView(subview)
        }
    }
    return nil
}

答案 3 :(得分:5)

Ashley Mills的更新解决方案(适用于iOS 7.x)

if (editing) {
    UIView *scrollView = self.subviews[0];
    for (UIView * view in scrollView.subviews) {
        NSLog(@"Class: %@", NSStringFromClass([view class]));
        if ([NSStringFromClass([view class]) rangeOfString: @"Reorder"].location != NSNotFound) {
            for (UIView * subview in view.subviews) {
                if ([subview isKindOfClass: [UIImageView class]]) {
                    ((UIImageView *)subview).image = [UIImage imageNamed: @"moveCellIcon"];
                }
            }
        }
    }
}

答案 4 :(得分:4)

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    for (UIControl *control in cell.subviews)
    {       
        if ([control isMemberOfClass:NSClassFromString(@"UITableViewCellReorderControl")] && [control.subviews count] > 0)
        {           
            for (UIControl *someObj in control.subviews)
            {
                if ([someObj isMemberOfClass:[UIImageView class]])
                {
                    UIImage *img = [UIImage imageNamed:@"reorder_icon.png"];
                    ((UIImageView*)someObj).frame = CGRectMake(0.0, 0.0, 43.0, 43.0);
                    ((UIImageView*)someObj).image = img;
                }
            }
        }
    }   
}

答案 5 :(得分:4)

我使用editingAccessoryView替换重新排序图标。

  1. 创建UITableViewCell的子类。
  2. 覆盖setEditing。只需隐藏重新排序控件,并使用重新订购的图像将editAccessoryView设置为uiimageview。
  3.  - (void) setEditing:(BOOL)editing animated:(BOOL)animated
    {
    
        [super setEditing: editing animated: YES];
    
        self.showsReorderControl = NO;
    
        self.editingAccessoryView = editing ? [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"yourReorderIcon"]] : nil;
    
    }
    

    如果您不使用编辑附件视图,这可能是一个不错的选择。

答案 6 :(得分:4)

雨燕4

$cd C:\Users\Admin\CLionProjects\project\src
$gcc -I ..\include main.c

答案 7 :(得分:1)

调试UITableViewCell后,可以使用UITableViewCell子类中的KVC对其进行更改。

// key
static NSString * const kReorderControlImageKey = @"reorderControlImage";

// setting when cellForRow calling
UIImage *customImage;
[self setValue:customImage forKeyPath:kReorderControlImageKey];

// to prevent crash
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    if ([key isEqualToString:kReorderControlImageKey]) return;
    else [super setValue:value forUndefinedKey:key];
}

答案 8 :(得分:0)

您也可以简单地将自己的自定义重新排序视图添加到单元格内的所有其他视图上。

您所要做的就是确保此自定义视图始终高于其他视图,可以在[UITableViewDelegate tableView: willDisplayCell: forRowAtIndexPath: indexPath:].

中查看

为了允许标准重新订购控制互动,您的自定义视图必须将其userInteractionEnabled设置为NO。

根据细胞的外观,您可能需要一个或多或少复杂的自定义重新排序视图(以模拟单元格背景为例)。

答案 9 :(得分:0)

我在iOS 12上使用Swift 4.2做到了这一点

我希望这会有所帮助:

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        for view in cell.subviews {
            if view.self.description.contains("UITableViewCellReorderControl") {
                for sv in view.subviews {
                    if (sv is UIImageView) {
                        (sv as? UIImageView)?.image = UIImage(named: "your_image")
                        (sv as? UIImageView)?.contentMode = .center
                        sv.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
                    }
                }
            }
        }
    }

答案 10 :(得分:0)

我没有其他答案可以为我工作,但是我找到了解决方法。

Grzegorz R. Kulesza的答案几乎对我有用,但我必须进行一些更改。

这可用于 Swift 5 iOS 13

// Change default reorder icon in UITableViewCell
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let imageView = cell.subviews.first(where: { $0.description.contains("Reorder") })?.subviews.first(where: { $0 is UIImageView }) as? UIImageView
    imageView?.image = UIImage(named: "your_custom_reorder_icon.png")
    let size = cell.bounds.height * 0.6 // scaled for padding between cells
    imageView?.frame.size.width = size
    imageView?.frame.size.height = size
}