web-dev-qa-db-fra.com

Comment créer une police et une couleur personnalisées dans UITableViewRowAction sans Storyboard

J'ai classique TableView où vous pouvez supprimer l'élément si vous glissez et que de cliquer sur le bouton. Je sais comment définir un arrière-plan personnalisé sur la cellule, mais je ne trouve pas comment je peux définir une police et une couleur personnalisées pour cela.

Merci pour l'aide!

func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]?  {

    var deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, 
                   title: "Delete", 
                   handler: { 
                      (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
                           println("Delete button clicked!")
                   })

    deleteAction.backgroundColor = UIColor.redColor()

    return [deleteAction]
}
11
Vlastimil Fiser

Eh bien, le seul moyen que j’ai trouvé de définir une police personnalisée est d’utiliser la méthode appearanceWhenContainedIn du protocole UIAppearance. Cette méthode n'est pas encore disponible dans Swift, vous devez donc le faire dans Objective-C.

J'ai créé une méthode de classe dans un utilitaire Objective-C pour la configurer:

+ (void)setUpDeleteRowActionStyleForUserCell {

    UIFont *font = [UIFont fontWithName:@"AvenirNext-Regular" size:19];

    NSDictionary *attributes = @{NSFontAttributeName: font,
                      NSForegroundColorAttributeName: [UIColor whiteColor]};

    NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString: @"DELETE"
                                                                          attributes: attributes];

    /*
     * We include UIView in the containment hierarchy because there is another button in UserCell that is a direct descendant of UserCell that we don't want this to affect.
     */
    [[UIButton appearanceWhenContainedIn:[UIView class], [UserCell class], nil] setAttributedTitle: attributedTitle
                                                                                          forState: UIControlStateNormal];
}

Cela fonctionne, mais ce n'est certainement pas idéal. Si vous n'incluez pas UIView dans la hiérarchie du confinement, cela affectera également l'indicateur de divulgation (je ne savais même pas que l'indicateur de divulgation était une sous-classe UIButton). En outre, si vous avez un bouton UIB dans votre cellule qui se trouve dans une sous-vue de la cellule, ce bouton sera également affecté par cette solution.

Compte tenu des complications, il serait peut-être préférable d'utiliser l'une des bibliothèques open source les plus personnalisables disponibles pour les options de balayage des cellules du tableau.

10
Logan Gauthier

Si vous utilisez la hiérarchie de la vue de débogage de XCode pour examiner ce qui se passe dans UITableView lorsque les boutons de balayage sont actifs, vous verrez que les éléments UITableViewRowAction sont convertis en bouton appelé _UITableViewCellActionButton, contenu dans UITableViewCellDeleteConfirmationView. Une façon de modifier les propriétés d'un bouton consiste à l'intercepter lorsqu'il est ajouté à UITableViewCell. Dans votre classe dérivée UITableViewCell, écrivez quelque chose comme ceci:

private let buttonFont = UIFont.boldSystemFontOfSize(13)
private let confirmationClass: AnyClass = NSClassFromString("UITableViewCellDeleteConfirmationView")!

override func addSubview(view: UIView) {
    super.addSubview(view)

    // replace default font in swipe buttons
    let s = subviews.flatMap({$0}).filter { $0.isKindOfClass(confirmationClass) }
    for sub in s {
        for button in sub.subviews {
            if let b = button as? UIButton {
                b.titleLabel?.font = buttonFont
            }
        }
    }
}
2
apetrovic

Je souhaite partager ma solution pour ObjC , il s’agit là d’une astuce mais qui fonctionne comme prévu. 

- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // this just convert view to `UIImage`
    UIImage *(^imageWithView)(UIView *) = ^(UIView *view) {

        UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
        [view.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    };

    // This is where the magic happen,
    // The width and height must be dynamic (it's up to you how to implement it)
    // to keep the alignment of the label in place
    //
    UIColor *(^getColorWithLabelText)(NSString*, UIColor*, UIColor*) = ^(NSString *text, UIColor *textColor, UIColor *bgColor) {

        UILabel *lbDelete = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 47, 40)];
        lbDelete.font = [UIFont boldSystemFontOfSize:11];
        lbDelete.text = text;
        lbDelete.textAlignment = NSTextAlignmentCenter;
        lbDelete.textColor = textColor;
        lbDelete.backgroundColor = bgColor;

        return [UIColor colorWithPatternImage:imageWithView(lbDelete)];
    };

    // The `title` which is `@"   "` is important it 
    // gives you the space you needed for the 
    // custom label `47[estimated width], 40[cell height]` on this example
    //
    UITableViewRowAction *btDelete;
    btDelete = [UITableViewRowAction
                rowActionWithStyle:UITableViewRowActionStyleDestructive
                title:@"   "
                handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
                    NSLog(@"Delete");
                    [tableView setEditing:NO];
                }];
    // Implementation
    //
    btDelete.backgroundColor = getColorWithLabelText(@"Delete", [UIColor whiteColor], [YJColor colorWithHexString:@"fe0a09"]);

    UITableViewRowAction *btMore;
    btMore   = [UITableViewRowAction
                rowActionWithStyle:UITableViewRowActionStyleNormal
                title:@"   "
                handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
                    NSLog(@"More");
                    [tableView setEditing:NO];
                }];
    // Implementation
    //
    btMore.backgroundColor = getColorWithLabelText(@"More", [UIColor darkGrayColor], [YJColor colorWithHexString:@"46aae8"]);

    return @[btMore, btDelete];
}

[YJColor colorWithHexString:<NSString>]; consiste simplement à convertir une chaîne hexadécimale en UIColor.

Vérifiez l'exemple de capture d'écran de sortie. 
 enter image description here

2
0yeoj

Cela semble fonctionner, du moins pour définir la couleur de la police:

- (void)setupRowActionStyleForTableViewSwipes {
    UIButton *appearanceButton = [UIButton appearanceWhenContainedInInstancesOfClasses:@[[NSClassFromString(@"UITableViewCellDeleteConfirmationView") class]]];
    [appearanceButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
}
0
Alexandru