Kyle Somers
Kyle Somers

Reputation: 632

Change Reorder Control's color in table view cell

In the image below, how do I change the color of the buttons on the right hand side of the view to white?edit: Ideally only want it to be white for certain cells and black for others Here's my code:

cell.backgroundColor = .appOrange
cell.contentLabel.textColor = .white
cell.numberLabel.textColor = .white
cell.tintColor = .white //this appears to do nothing, just something I tried

enter image description here

Upvotes: 20

Views: 7459

Answers (6)

Nick Entin
Nick Entin

Reputation: 1087

In iOS13.x seems like reorder control's color is dependent on the Light/Dark mode (earlier it was set on contrast with background, now it appears fixed depending on the mode). Therefore there is a possibility to switch color of the reorder control by overrideUserInterfaceStyle of the UITableViewCell.

Default - in the light mode of the phone I get practically invisible controls:

Default - in the light mode of the phone I get practically invisible controls

Now applying

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
    SelectableCell *cell = [tableView     dequeueReusableCellWithIdentifier:@"selectableCell"];
    ...
    cell.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;

   return cell;
}

gives following result:

Overriding - UI style

Upvotes: 20

Genki
Genki

Reputation: 3195

And just in case if anyone is going back in time, here's Objective-C version of mikkel-cortnum's answer:

@implementation TintedReorderedCell

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

    for (UIView *subViewA in self.subviews) {
        if ([NSStringFromClass(subViewA.class) isEqualToString:@"UITableViewCellReorderControl"]) {
            for (UIView *subViewB in subViewA.subviews) {
                if ([subViewB isKindOfClass:UIImageView.class]) {
                    UIImageView *imageView = ((UIImageView *)subViewB);
                    imageView.image = [imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
                    imageView.tintColor = [UIColor redColor];
                    break;
                }
            }
            break;
        }
    }
}

@end

Upvotes: 5

hardyfelix
hardyfelix

Reputation: 222

I use an extension to find the reorder control imageView.

extension UITableViewCell {

    var reorderControlImageView: UIImageView? {
        let reorderControl = self.subviews.first { view -> Bool in
            view.classForCoder.description() == "UITableViewCellReorderControl"
        }
        return reorderControl?.subviews.first { view -> Bool in
            view is UIImageView
        } as? UIImageView
    }
}

In willDisplay I update the tintColor of the image view.

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cell.reorderControlImageView?.tint(color: Color.text.uiColor)
}

Setting a tint color with a UIImageView extension

extension UIImageView {

    func tint(color: UIColor) {
        self.image = self.image?.withRenderingMode(.alwaysTemplate)
        self.tintColor = color
    }
}

Upvotes: 16

Mikkel Cortnum
Mikkel Cortnum

Reputation: 622

With inspiration from Thomas answer above, I found a solution that works for me.

Trying Thomas solution, I was faced with the problem, that it does not update the view for cells that are already displayed. Therefore I chose to overwrite the setEditing method on my custom cells instead.

private var myReorderImage: UIImage? = nil

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

    for subViewA in self.subviews {
        if (subViewA.classForCoder.description() == "UITableViewCellReorderControl") {
            for subViewB in subViewA.subviews {
                if (subViewB.isKind(of: UIImageView.classForCoder())) {
                    let imageView = subViewB as! UIImageView;
                    if (self.myReorderImage == nil) {
                        let myImage = imageView.image;
                        myReorderImage = myImage?.withRenderingMode(.alwaysTemplate);
                    }
                    imageView.image = self.myReorderImage;
                    imageView.tintColor = .red;
                    break;
                }
            }
            break;
        }
    }
}

Upvotes: 9

Thomas
Thomas

Reputation: 515

This works for me in my UITableViewController using iOS11 and Swift 4:

private var myReorderImage : UIImage? = nil;

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    for subViewA in cell.subviews {
        if (subViewA.classForCoder.description() == "UITableViewCellReorderControl") {
            for subViewB in subViewA.subviews {
                if (subViewB.isKind(of: UIImageView.classForCoder())) {
                    let imageView = subViewB as! UIImageView;
                    if (myReorderImage == nil) {
                        let myImage = imageView.image;
                        myReorderImage = myImage?.withRenderingMode(UIImageRenderingMode.alwaysTemplate);
                    }
                    imageView.image = myReorderImage;
                    imageView.tintColor = UIColor.red;
                    break;
                }
            }
            break;
        }
    }
}

Upvotes: 13

Kyle Somers
Kyle Somers

Reputation: 632

Unless something changes in Swift or someone else manages to dig up an answer, I researched this pretty well, and it looks like there isn't a way to do it without changing the UIReorderControl file, which will probably get your app rejected.

My solution is to implement the "long tap and drag," which there are tutorials on online. It's not ideal and not incredibly easy to implement unfortunately.

Upvotes: 1

Related Questions