Qual è il modo migliore per cambiare il colore / vista della divulgazione indicatore di vista accessorio in una visualizzazione cella di una tabella in iOS?

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

Domanda

Ho bisogno di cambiare il colore dell'accessorio disclosureIndicatorView in un UITableViewCell. Penso che ci sono due modi per ottenere questo fatto, ma non sono in grado di capire quale è l'optimum. Così qui è quello che penso che posso fare.

C'è una proprietà di UITableViewCell - accessoryView. Così posso usare setAccessoryView:(UIView *)view e passare vista come il UIImageView tenendo l'immagine che voglio.

Ho scritto una classe di utilità che crea la vista dei contenuti (roba come colore di sfondo, l'aggiunta di altre cose, ecc) per il mio cellulare e ho aggiungere questo punto di vista il contenuto della cella in UITableViewDelegate. L'altra opzione è quella di disegnare un UIImage override del metodo drawRect di classe di utilità CustomContentView.

Esecuzione di opzione 1 - posso ottenere le cose fatte il modo in cui Apple. Basta dare loro la vista e fanno il resto. Ma immagino aggiungendo un nuovo oggetto UIView per ogni riga potrebbe rivelarsi un'allocazione oggetto pesante e diminuendo il frame rate. Rispetto ad un semplice oggetto UIImage nel mio contentView. Credo UIImage è più leggero di UIView.

Si prega di gettare un po 'di luce e persone aiutarmi a decidere su di esso.

È stato utile?

Soluzione

  

Ma immagino aggiungendo un nuovo oggetto UIView per ogni riga potrebbe rivelarsi un'allocazione obj pesante e diminuendo il frame rate. Rispetto ad un semplice oggetto UIImage nel mio contentView. Credo UIImage è più leggero di UIView.

Disegnare un'immagine direttamente quasi certamente avere prestazioni migliori rispetto l'aggiunta di una visualizzazione secondaria. È necessario determinare se che una performance migliore è necessario. Ho usato un paio di vista accessori per gli indicatori di informazione personalizzati sulle cellule di base e le prestazioni andava bene. Tuttavia, se si sta già facendo il disegno personalizzato per il rettangolo di contenuti, potrebbe non essere così difficile fare la vista accessorio anche.

Altri suggerimenti

Gran post su Cocoanetics che risolve questo. La classe UIControl eredita le proprietà selezionate, abilitato ed evidenziate personalizzata con colori a Indicatori Disclosure

Se siete interessati a elaborare l'indicatore, invece di utilizzare un file immagine, ecco il codice ho lavorato fuori per farlo:

// (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);

Se si effettua una sottoclasse UIView personalizzato, fare quanto sopra nel drawRect:. Metodo, e l'uso che come visualizzazione accessorio, sarete in grado di fare nulla al colore che si desidera

Una vista accessorio (personalizzata o UIImageView non sarà un grave problema di prestazioni fino a quando si sono il riciclaggio corretto casi UITableViewCell.

Ecco un'implementazione che funziona in iOS 8+. Fa esattamente quello ha chiesto di:
cambiare il colore dell'indicatore originale divulgazione Apple di un colore personalizzato.
 Utilizzare in questo modo:

#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

In rapido 3, ho adattato la soluzione da @galambalazs come estensione classe come segue:

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

Spero che questo aiuti un po '.

Utilizzare un UIImageView. Questo permetterà anche di cambiare l'immagine quando si seleziona la cella:

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

La soluzione di benzado funziona bene, ma ha mostrato un fondo nero. Nella classe UIView che si imposta (colui che è drawRect funzione si mette nel suo codice) deve avere la seguente implementazione initWithFrame in modo che la divulgazione di disegno per avere uno sfondo trasparente:

- (id)initWithFrame:(CGRect)frame {

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

Naturalmente, è possibile impostare questo a qualsiasi colore che si desidera ...

Mentre risposta galambalazs' funziona, si deve rilevare che si tratta di un po 'di un hack come si accede e aggiornamenti indirettamente implementazione privata di Apple dell'indicatore divulgazione. Nella migliore delle ipotesi, si potrebbe smettere di funzionare nelle future versioni di iOS, e nel peggiore dei casi portare ad App Store rifiuto. Impostazione del accessoryView è ancora il metodo approvato fino a quando Apple espone una proprietà per impostare direttamente il colore.

In ogni caso, qui è l'implementazione Swift della sua risposta per coloro che lo vogliono:

Nota: cell.disclosureIndicatorColor deve essere impostato dopo cell.accessoryType = .DisclosureIndicator è impostato in modo che il pulsante disclosureIndicator è disponibile in subviews della cella:

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

Cambia il colore della tinta della cella di vista tabella. Controllare lo screenshot di fare lo stesso tramite Storyboard

Come contributo alla soluzione di @benzado I swiftified il suo codice come segue:

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

Con un cambiamento del colore applicazione una chiamata a setNeedsDisplay () sul UITableCellView aggiornerà il colore. Mi piace di evitare l'uso di oggetti UIImage nelle viste di cella.

Un rapido 3 versione dei CocoaNetics soluzione

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()
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top