How to change UITableViewRowAction title color?

北慕城南 提交于 2019-11-26 13:52:32

问题


Am using UITableViewRowAction in "editActionsForRowAtIndexPath" method. I can change the backgroundcolor of UITableViewRowAction, but am not able to change the title color. But I would like to change the color of the UITableViewRowAction. Any inputs on this regard will be appreciable.


回答1:


I'm afraid that there's no way to change the title color of the UITableViewRowAction.

The only things you can change on the action are:

  • backgroundColor
  • style (destructive (red backgroundcolor, ...)
  • title

For more info, please refer to the Apple Doc UITableViewRowAction




回答2:


There is one way that can achieve what you are looking for. But it is little tricky though.

Example of result:

The idea of this trick is that you can actually modify background color. This means that you can set UIColor's +colorWithPatternImage: and set an bitmap image that match desired styling. This can be achieved either by creating image using graphic editor or by rendering it using for example Core Graphics. The only problem with this solution is, that you have to mimic original title length with you specific text attributes to make it work properly and also you must set title for table view row action as string of white spaces so that table view cell will prepare enough space for you "custom action button". Creating static png assets in photoshop may be inappropriate if you use variable cell rows.

This is category for NSString that creates string of empty spaces that will create space for your custom button and second will generate bitmap image that will be placed as background pattern image. For parameters you must set text attributes for original title, that is basically @{NSFontAttributeName: [UIFont systemFontOfSize:18]}, than your desired text attributes. Maybe there is better way to achieve this :)

@implementation NSString (WhiteSpace)

- (NSString *)whitespaceReplacementWithSystemAttributes:(NSDictionary *)systemAttributes newAttributes:(NSDictionary *)newAttributes
{
    NSString *stringTitle = self;
    NSMutableString *stringTitleWS = [[NSMutableString alloc] initWithString:@""];

    CGFloat diff = 0;
    CGSize  stringTitleSize = [stringTitle sizeWithAttributes:newAttributes];
    CGSize stringTitleWSSize;
    NSDictionary *originalAttributes = systemAttributes;
    do {
        [stringTitleWS appendString:@" "];
        stringTitleWSSize = [stringTitleWS sizeWithAttributes:originalAttributes];
        diff = (stringTitleSize.width - stringTitleWSSize.width);
        if (diff <= 1.5) {
            break;
        }
    }
    while (diff > 0);

    return [stringTitleWS copy];
}

@end

Second important part is code that renders bitmap that can be used as pattern image for UITableViewRowAction's backgroundColor.

- (UIImage *)imageForTableViewRowActionWithTitle:(NSString *)title textAttributes:(NSDictionary *)attributes backgroundColor:(UIColor *)color cellHeight:(CGFloat)cellHeight
{
    NSString *titleString = title;
    NSDictionary *originalAttributes = @{NSFontAttributeName: [UIFont systemFontOfSize:18]};
    CGSize originalSize = [titleString sizeWithAttributes:originalAttributes];
    CGSize newSize = CGSizeMake(originalSize.width + kSystemTextPadding + kSystemTextPadding, originalSize.height);
    CGRect drawingRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, cellHeight));
    UIGraphicsBeginImageContextWithOptions(drawingRect.size, YES, [UIScreen mainScreen].nativeScale);
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(contextRef, color.CGColor);
    CGContextFillRect(contextRef, drawingRect);

    UILabel *label = [[UILabel alloc] initWithFrame:drawingRect];
    label.textAlignment = NSTextAlignmentCenter;
    label.attributedText = [[NSAttributedString alloc] initWithString:title attributes:attributes];
    [label drawTextInRect:drawingRect];

    //This is other way how to render string 
    //    CGSize size = [titleString sizeWithAttributes:attributes];
    //    CGFloat x =  (drawingRect.size.width - size.width)/2;
    //    CGFloat y =  (drawingRect.size.height - size.height)/2;
    //    drawingRect.origin = CGPointMake(x, y);
    //    [titleString drawInRect:drawingRect withAttributes:attributes];

    UIImage *returningImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return returningImage;
}

And then when you are creating your row action you can do something like this:

NSDictionary *systemAttributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:18] };
NSDictionary *newAttributes = @{NSFontAttributeName: [UIFont fontWithName:@"Any font" size:15]};
NSString *actionTitle = @"Delete";
NSString *titleWhiteSpaced = [actionTitle whitespaceReplacementWithSystemAttributes:systemTextFontAttributes newAttributes:newAttributes];
UITableViewRowAction *rowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:titleWhiteSpaced handle:NULL];
UIImage *patternImage = [self imageForTableViewRowActionWithTitle:actionTitle textAttributes:newAttributes backgroundColor:[UIColor redColor] cellHeight:50];
rowAction.backgroundColor = [UIColor colorWithPatternImage:patternImage]; 

This solution is obviously hacky but you can achieve desired results without using private APIs and in future if something breaks, this will not break your app. Only button will look inappropriate.

Example of result:

This code has of course a lot of space for improvements, any suggestions are appreciated.




回答3:


Swift

No need to mess with UIButton.appearance...

Put this in your cell's class and change UITableViewCellActionButton according to your needs.

override func layoutSubviews() {

    super.layoutSubviews()

    for subview in self.subviews {

        for subview2 in subview.subviews {

            if (String(subview2).rangeOfString("UITableViewCellActionButton") != nil) {

                for view in subview2.subviews {

                    if (String(view).rangeOfString("UIButtonLabel") != nil) {

                        if let label = view as? UILabel {

                            label.textColor = YOUR COLOUR
                        }

                    }
                }
            }
        }
    }

}



回答4:


There is indeed a way to change the title color of the UITableViewRowAction. It's a button. You can use the UIButton appearance proxy:

[[UIButton appearance] setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];




回答5:


Lee Andrew's answer in Swift 3 / Swift 4:

class MyCell: UITableViewCell {

    override func layoutSubviews() {
        super.layoutSubviews()

        for subview in self.subviews {

            for sub in subview.subviews {

                if String(describing: sub).range(of: "UITableViewCellActionButton") != nil {

                    for view in sub.subviews {

                        if String(describing: view).range(of: "UIButtonLabel") != nil {

                            if let label = view as? UILabel {

                                label.textColor = UIColor.black

                            }

                        }

                    }

                }

            }

        }

    }

}



回答6:


iOS 11 solution:

Create UITableViewCell extension like this:

extension UITableViewCell {

    /// Returns label of cell action button.
    ///
    /// Use this property to set cell action button label color.
    var cellActionButtonLabel: UILabel? {
        for subview in self.superview?.subviews ?? [] {
            if String(describing: subview).range(of: "UISwipeActionPullView") != nil {
                for view in subview.subviews {
                    if String(describing: view).range(of: "UISwipeActionStandardButton") != nil {
                        for sub in view.subviews {
                            if let label = sub as? UILabel {
                                return label
                            }
                        }
                    }
                }
            }
        }
        return nil
    }

}

And write this in your UITableViewCell

override func layoutSubviews() {
    super.layoutSubviews()
    cellActionButtonLabel?.textColor = .red
}

But there is a bug - if you pull the cell fast this code sometimes doesn't change the color.




回答7:


You can add these two functions in your UITableViewCell subclass and call the setActionButtonsTitleColor function to set action buttons' title color.

func setActionButtonsTitleColor(color: UIColor) {
  let actionButtons: [UIButton] = self.getActionButtons()

  for actionButton in actionButtons {
    actionButton.setTitleColor(color, for: .normal)
  }
}

func getActionButtons() -> [UIButton] {
  let actionButtons: [UIButton] = self.subviews.map {
    (view: UIView) -> [UIView] in
    return view.subviews
  }
  .joined()
  .filter {
    (view: UIView) -> Bool in
    return String(describing: view).contains("UITableViewCellActionButton")
  }.flatMap {
    (view: UIView) -> UIButton? in
    return view as? UIButton
  }

  return actionButtons
}



回答8:


-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewRowAction *editAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"edit" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
    {
    // Action something here

}];

editAction.backgroundColor = [UIColor whiteColor];
[[UIButton appearance] setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];

return @[editAction];



回答9:


IF someone is still looking for an alternative solution:

You can use the swipecellkit pod

https://github.com/SwipeCellKit/SwipeCellKit

This lets you customize the label color, image color and even the entire background while perserving the actual look and feel of the native implementation.



来源:https://stackoverflow.com/questions/26887563/how-to-change-uitableviewrowaction-title-color

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!