web-dev-qa-db-fra.com

Comment changer la couleur du titre UITableViewRowAction?

J'utilise UITableViewRowAction dans la méthode "editActionsForRowAtIndexPath". Je peux changer la couleur de fond de UITableViewRowAction, mais je ne peux pas changer la couleur du titre. Mais je voudrais changer la couleur de UITableViewRowAction. Toute contribution à cet égard sera appréciable.

14
GJDK

Je crains qu'il n'y ait aucun moyen de changer la couleur du titre de UITableViewRowAction.

Les seules choses que vous pouvez changer dans l'action sont:

  • couleur de fond
  • style (destructif (couleur de fond rouge, ...)
  • titre

Pour plus d'informations, reportez-vous au Apple Doc UITableViewRowAction

8
Thomas Keuleers

Il existe un moyen d’atteindre ce que vous recherchez. Mais c'est quand même un peu délicat. 

Exemple de résultat:

enter image description here

L'idée de cette astuce est que vous pouvez réellement modifier la couleur de fond. Cela signifie que vous pouvez définir + colorWithPatternImage: de UIColor et définir une image bitmap correspondant au style souhaité. Cela peut être réalisé soit en créant une image à l'aide de l'éditeur graphique, soit en la rendant à l'aide, par exemple, de Core Graphics. Le seul problème avec cette solution est que vous devez imiter la longueur du titre original avec vos attributs de texte spécifiques pour le faire fonctionner correctement et vous devez également définir le titre de l'action de ligne de la vue tableau sous la forme d'une chaîne d'espaces blancs afin que la cellule de la vue tableau se prépare suffisamment espace pour vous "bouton d'action personnalisé". La création d'actifs png statiques dans photoshop peut être inappropriée si vous utilisez des lignes de cellules variables. 

C'est la catégorie pour NSString qui crée une chaîne d'espaces vides qui créeront un espace pour votre bouton personnalisé et la seconde générera une image bitmap qui sera placée en tant qu'image de modèle d'arrière-plan. Pour les paramètres, vous devez définir des attributs de texte pour le titre d'origine, c'est-à-dire @{NSFontAttributeName: [UIFont systemFontOfSize:18]}, plutôt que pour les attributs de texte souhaités. Peut-être y a-t-il un meilleur moyen d'y parvenir :)

@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

La deuxième partie importante est le code qui rend l'image bitmap qui peut être utilisée comme image de modèle pour backgroundColor de UITableViewRowAction.

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

Et ensuite, lorsque vous créez votre action de rangée, vous pouvez faire quelque chose comme ceci:

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

Cette solution est évidemment astucieuse, mais vous pouvez obtenir les résultats souhaités sans utiliser d'API privée et, à l'avenir, en cas de problème, votre application ne sera pas endommagée. Seul le bouton semblera inapproprié. 

Exemple de résultat:

enter image description here

Ce code a bien sûr beaucoup de place pour des améliorations, toutes les suggestions sont les bienvenues.

18
Peter Stajger

Rapide

Pas besoin de jouer avec UIButton.appearance ...

Mettez ceci dans votre classe de cellules et changez le bouton d'action UITableViewCell en fonction de vos besoins. 

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
                        }

                    }
                }
            }
        }
    }

}
10
Lee Andrew

Il existe en effet un moyen de changer la couleur du titre de UITableViewRowAction. C'est un bouton. Vous pouvez utiliser le proxy d'apparence UIButton:

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

enter image description here

6
ToddB

Réponse de Lee Andrew 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

                            }

                        }

                    }

                }

            }

        }

    }

}
5
David Seek

Vous pouvez ajouter ces deux fonctions dans votre sous-classe UITableViewCell et appeler la fonction setActionButtonsTitleColor pour définir la couleur de titre des boutons d'action.

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
}
1
Oleksiy Kovtun

iOS 11 solution:

Créez une extension UITableViewCell comme ceci:

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
    }

}

Et écrivez ceci dans votre UITableViewCell

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

Mais il y a un bug - si vous tirez la cellule rapidement ce code ne change parfois pas la couleur.

1
Ivan Smetanin
-(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];
0
JHT

SI quelqu'un cherche toujours une solution alternative:

Vous pouvez utiliser le pod swipecellkit 

https://github.com/SwipeCellKit/SwipeCellKit

Cela vous permet de personnaliser la couleur de l'étiquette, la couleur de l'image et même tout l'arrière-plan tout en préservant l'apparence réelle de la mise en œuvre native.

0
Leo van der Zee