Quelle est la meilleure façon de changer la couleur / vue de vue accessoire indicateur communication dans une cellule de vue de la table dans iOS?

StackOverflow https://stackoverflow.com/questions/1852672

Question

Je dois changer la couleur de l'accessoire de disclosureIndicatorView dans un UITableViewCell. Je pense qu'il ya deux façons d'y parvenir, mais je ne suis pas en mesure de comprendre que l'on est l'optimum. Voici donc ce que je pense que je peux le faire.

Il y a une propriété de UITableViewCell - accessoryView. Je peux donc utiliser setAccessoryView:(UIView *)view et passer vue comme UIImageView tenant l'image que je veux.

J'ai écrit une classe utilitaire qui crée l'affichage du contenu (des choses comme la couleur d'arrière-plan, en ajoutant d'autres choses, etc) pour ma cellule et j'ajouter ce point de vue du contenu à la cellule dans UITableViewDelegate. L'autre option consiste à dessiner un UIImage remplaçant la méthode de drawRect de classe utilitaire CustomContentView.

Option Exécution 1 - je peux obtenir des choses fait le chemin de la pomme. Il suffit de leur donner la vue et ils font le reste. Mais je suppose que l'ajout d'un nouvel objet UIView à chaque ligne pourrait se révéler une allocation d'objets lourds et en diminuant la vitesse de défilement. Par rapport à seulement un objet UIImage dans mon contentView. Je crois UIImage est plus léger que UIView.

S'il vous plaît jeter certaines personnes lumière et aidez-moi à décider dessus.

Était-ce utile?

La solution

  

Mais je suppose que l'ajout d'un nouvel objet UIView à chaque ligne peut se révéler une allocation lourde obj et en diminuant la vitesse de défilement. Par rapport à seulement un objet UIImage dans mon contentView. Je crois UIImage est plus léger que UIView.

Dessiner une image directement aura certainement de meilleures performances que l'ajout d'un sous-vue. Vous devez déterminer si cette performance supplémentaire est nécessaire. Je l'ai utilisé quelques vues accessoires pour les indicateurs d'information personnalisés sur les cellules de base et la performance était bien. Toutefois, si vous faites déjà dessin personnalisé pour le rect contenu, il pourrait ne pas être si difficile à faire le point de vue accessoire aussi.

Autres conseils

Grande poste sur Cocoanetics qui traite de ce problème. La classe UIControl hérite des propriétés sélectionnées, activé et mis en évidence Indicateurs d'information sur mesure de couleur

Si vous êtes intéressé à tirer l'indicateur, au lieu d'utiliser un fichier image, voici le code que je travaille sur le faire:

// (x,y) is the tip of the arrow
CGFloat x = CGRectGetMaxX(self.bounds) - RIGHT_MARGIN;
CGFloat y = CGRectGetMidY(self.bounds);
const CGFloat R = 4.5;
CGContextRef ctxt = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(ctxt, x-R, y-R);
CGContextAddLineToPoint(ctxt, x, y);
CGContextAddLineToPoint(ctxt, x-R, y+R);
CGContextSetLineCap(ctxt, kCGLineCapSquare);
CGContextSetLineJoin(ctxt, kCGLineJoinMiter);
CGContextSetLineWidth(ctxt, 3);
// If the cell is highlighted (blue background) draw in white; otherwise gray
if (CONTROL_IS_HIGHLIGHTED) {
    CGContextSetRGBStrokeColor(ctxt, 1, 1, 1, 1);
} else {
    CGContextSetRGBStrokeColor(ctxt, 0.5, 0.5, 0.5, 1);
}
CGContextStrokePath(ctxt);

Si vous faites une sous-classe UIView personnalisée, faites ci-dessus dans la drawRect:. Méthode, et l'utiliser comme votre point de vue accessoire, vous serez en mesure de faire quoi que ce soit de la couleur que vous voulez

Une vue accessoire (sur mesure ou UIImageView ne sera pas un problème majeur de performance aussi longtemps que vous recyclez bien des cas UITableViewCell.

Voici une implémentation qui fonctionne dans iOS 8+. Il fait exactement c'est demandé:
changer la couleur de l'indicateur d'information d'origine Apple à une couleur personnalisée.  Utilisez comme ceci:

#import "UITableViewCell+DisclosureIndicatorColor.h"
// cell is a UITableViewCell
cell.disclosureIndicatorColor = [UIColor redColor]; // custom color
[cell updateDisclosureIndicatorColorToTintColor]; // or use global tint color

UITableViewCell + DisclosureIndicatorColor.h

@interface UITableViewCell (DisclosureIndicatorColor)
@property (nonatomic, strong) UIColor *disclosureIndicatorColor;
- (void)updateDisclosureIndicatorColorToTintColor;
@end

UITableViewCell + DisclosureIndicatorColor.m

@implementation UITableViewCell (DisclosureIndicatorColor)

- (void)updateDisclosureIndicatorColorToTintColor {
    [self setDisclosureIndicatorColor:self.window.tintColor];
}

- (void)setDisclosureIndicatorColor:(UIColor *)color {
    NSAssert(self.accessoryType == UITableViewCellAccessoryDisclosureIndicator,
        @"accessory type needs to be UITableViewCellAccessoryDisclosureIndicator");

    UIButton *arrowButton = [self arrowButton];
    UIImage *image = [arrowButton backgroundImageForState:UIControlStateNormal];
    image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    arrowButton.tintColor = color;
    [arrowButton setBackgroundImage:image forState:UIControlStateNormal];
}

- (UIColor *)disclosureIndicatorColor {
    NSAssert(self.accessoryType == UITableViewCellAccessoryDisclosureIndicator, 
        @"accessory type needs to be UITableViewCellAccessoryDisclosureIndicator");

    UIButton *arrowButton = [self arrowButton];
    return arrowButton.tintColor;
}

- (UIButton *)arrowButton {
    for (UIView *view in self.subviews)
        if ([view isKindOfClass:[UIButton class]])
            return (UIButton *)view;
    return nil;
}

@end

3 rapide, j'ai adapté la solution de @galambalazs comme une extension de classe comme suit:

import UIKit

extension UITableViewCell {

    func setDisclosure(toColour: UIColor) -> () {
        for view in self.subviews {
            if let disclosure = view as? UIButton {
                if let image = disclosure.backgroundImage(for: .normal) {
                    let colouredImage = image.withRenderingMode(.alwaysTemplate);
                    disclosure.setImage(colouredImage, for: .normal)
                    disclosure.tintColor = toColour
                }
            }
        }
    }
}

Espérons que cela aide certains.

Utilisez un UIImageView. Cela vous permettra également de changer l'image lorsque la cellule est sélectionnée:

UIImageView* arrowView = [[UIImageView alloc] initWithImage:normalImage];
arrowView.highlightedImage = selectedImage;
cell.accessoryView = arrowView;
[arrowView release];

La solution de benzado fonctionne très bien, mais il a montré un fond noir. Dans la classe UIView que vous configurez (celui qui est drawRect fonction que vous mettez dans son code) doit avoir la mise en œuvre initWithFrame suivante pour que la divulgation de dessin pour avoir un fond transparent:

- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
        [self setBackgroundColor:[UIColor clearColor]];
        // Initialization code.
    }
    return self;
}

Bien sûr, vous pouvez mettre ce que la couleur que vous voulez ...

Alors que la réponse de galambalazs fonctionne, il convient de noter qu'il est un peu un hack car il accède indirectement et des mises à jour d'Apple mise en œuvre privée de l'indicateur de divulgation. Au mieux, il pourrait cesser de fonctionner dans les futurs iOS versions, et au pire entraîner le rejet App Store. Réglage de la accessoryView est toujours la méthode approuvée jusqu'à ce qu'Apple expose une propriété pour la mise directement la couleur.

Peu importe, voici la mise en œuvre rapide de sa réponse pour ceux qui le veulent:

Remarque: cell.disclosureIndicatorColor doit être réglé après cell.accessoryType = .DisclosureIndicator est réglé de telle sorte que le bouton disclosureIndicator est disponible dans les sous-vues de la cellule:

extension UITableViewCell {

    public var disclosureIndicatorColor: UIColor? {
        get {
            return arrowButton?.tintColor
        }
        set {
            var image = arrowButton?.backgroundImageForState(.Normal)
            image = image?.imageWithRenderingMode(.AlwaysTemplate)
            arrowButton?.tintColor = newValue
            arrowButton?.setBackgroundImage(image, forState: .Normal)
        }
    }

    public func updateDisclosureIndicatorColorToTintColor() {
        self.disclosureIndicatorColor = self.window?.tintColor
    }

    private var arrowButton: UIButton? {
        var buttonView: UIButton?
        self.subviews.forEach { (view) in
            if view is UIButton {
                buttonView = view as? UIButton
                return
            }
        }
        return buttonView
    }
}

Changer la couleur de la teinte de la table cellule de vue. Vérifiez la capture d'écran pour faire la même chose via Storyboard

En tant que contribution à la solution de @benzado je swiftified son code comme suit:

override func drawRect(rect: CGRect) {

  super.drawRect(rect)

  let context = UIGraphicsGetCurrentContext();

  let right_margin : CGFloat = 15.0
  let length : CGFloat = 4.5;

  // (x,y) is the tip of the arrow
  let x = CGRectGetMaxX(self.bounds) - right_margin;
  let y = CGRectGetMidY(self.bounds);

  CGContextMoveToPoint(context, x - length, y - length);
  CGContextAddLineToPoint(context, x, y);
  CGContextAddLineToPoint(context, x - length, y + length);
  CGContextSetLineCap(context, .Round);
  CGContextSetLineJoin(context, .Miter);
  CGContextSetLineWidth(context, 2.5);

  if (self.highlighted)
  {
    CGContextSetStrokeColorWithColor(context, UIColor.appColorSelected().CGColor);
  }
  else
  {
    CGContextSetStrokeColorWithColor(context, UIColor.appColor().CGColor);
  }

  CGContextStrokePath(context);
}

Avec un changement de la couleur de l'application d'un appel à setNeedsDisplay () sur la UITableCellView mettra à jour la couleur. Je tiens à éviter l'utilisation d'objets UIImage dans les vues de cellules.

A rapide 3 version des CocoaNetics solution

public class DisclosureIndicator: UIControl {

    public static func create(color: UIColor?, highlightedColor: UIColor?) -> DisclosureIndicator{
        let indicator = DisclosureIndicator(frame: CGRect(x: 0, y: 0, width: 11, height: 15))
        if let color = color { indicator.color = color }
        if let color = highlightedColor { indicator.highlightedColor = color }
        return indicator
    }

    public var color: UIColor = .black
    public var highlightedColor: UIColor = .white

    override public init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .clear
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        backgroundColor = .clear
    }

    override public func draw(_ rect: CGRect) {
        super.draw(rect)

        let context = UIGraphicsGetCurrentContext()!;

        // (x,y) is the tip of the arrow
        let x = self.bounds.maxX - 3.0;
        let y = self.bounds.midY;

        let length : CGFloat = 4.5;
        context.move(to: CGPoint(x: x - length, y: y - length))
        context.addLine(to: CGPoint(x: x, y: y))
        context.addLine(to: CGPoint(x: x - length, y: y + length))
        context.setLineCap(.round)
        context.setLineJoin(.miter)
        context.setLineWidth(3)

        context.setStrokeColor((isHighlighted ? highlightedColor : color).cgColor)

        context.strokePath()
    }

    override public var isHighlighted: Bool {
        get {
            return super.isHighlighted
        }
        set {
            super.isHighlighted = newValue
            setNeedsDisplay()
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top