Qual é a melhor maneira de mudar a cor / vista do indicador de divulgação vista acessório em uma célula de exibição de tabela no iOS?

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

Pergunta

Eu preciso mudar a cor do acessório disclosureIndicatorView em um UITableViewCell. Eu acho que existem duas maneiras de conseguir este feito, mas eu não sou capaz de descobrir qual é o ideal. Então aqui é o que eu acho que posso fazer.

Há uma propriedade de UITableViewCell - accessoryView. Então eu posso usar setAccessoryView:(UIView *)view e passar vista como o UIImageView segurando a imagem que eu quero.

Eu escrevi uma classe de utilitário que cria a exibição de conteúdo (coisas como cor de fundo, adicionando outras coisas, etc) para o meu celular e eu adicionar este ponto de vista de conteúdo para a célula em UITableViewDelegate. A outra opção é chamar um UIImage substituindo o método drawRect de classe de utilitário CustomContentView.

opção 1 Executar - eu posso conseguir as coisas feitas da maneira maçã. Basta dar-lhes a vista e eles fazem o resto. Mas eu acho que a adição de um novo objeto UIView para cada linha pode vir a ser uma alocação objeto pesado e diminuir a taxa de quadros. Em comparação com apenas um objeto UIImage na minha contentView. Acredito UIImage é mais leve que UIView.

Por favor, jogue algumas pessoas leves e me ajudar a decidir sobre ele.

Foi útil?

Solução

Mas eu acho que a adição de um novo objeto UIView para cada linha pode vir a ser uma alocação pesada obj e diminuindo a taxa de quadros. Em comparação com apenas um objeto UIImage no meu contentView. Acredito UIImage é mais leve que UIView.

Desenhar uma imagem diretamente quase certamente terá melhor desempenho do que a adição de um subexibição. Você tem que determinar se que o desempenho extra é necessário. Eu usei algumas vistas acessórias para os indicadores de divulgação personalizados em células básicas e desempenho estava bem. No entanto, se você já está fazendo desenho para o rect conteúdo personalizado, ele pode não ser tão difícil de fazer o ponto de vista acessório também.

Outras dicas

Great post sobre Cocoanetics que aborda esse. Os herda classe UIControl as propriedades seleccionadas, activado e destacada Custom-coloridos indicadores Divulgação

Se você está interessado em desenhar o indicador, em vez de usar um arquivo de imagem, código de aqui eu trabalhei para fazê-lo:

// (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 você fizer uma subclasse UIView personalizado, faça o acima na drawRect: método, e usar isso como sua visão acessório, você vai ser capaz de fazer a cor que quiser

.

Uma visão acessório (personalizado ou UIImageView não será um grande problema de desempenho, desde que você está reciclando adequadamente casos UITableViewCell.

Aqui está uma implementação que funciona em iOS 8+. Ele faz exatamente o que é pedido para:
mudar a cor do indicador da Apple divulgação original para uma cor personalizada.
Usá-lo como este:

#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 rápida, que se adaptaram a solução de @galambalazs como uma extensão de classe como se 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
                }
            }
        }
    }
}

Espero que isso ajude alguns.

Use um UIImageView. Isso também permitirá que você alterar a imagem quando a célula é selecionada:

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

O benzado funciona bem, mas mostrou um fundo preto. Na classe UIView que você setup (o único que é drawRect função que você colocou no seu código) precisa ter a seguinte implementação initWithFrame para que a divulgação do desenho para ter um fundo transparente:

- (id)initWithFrame:(CGRect)frame {

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

Naturalmente, você pode definir isso ao que cor você quer ...

Enquanto obras resposta galambalazs, deve-se notar que é um pouco de um truque, uma vez que indiretamente acessa e atualiza implementação privada da Apple do indicador de divulgação. Na melhor das hipóteses, poderia parar de trabalhar no iOS futuros lançamentos, e na pior das hipóteses levar à rejeição App Store. Definir o accessoryView ainda é o método aprovado até que a Apple expõe uma propriedade para definir directamente a cor.

De qualquer maneira, aqui é a implementação Swift de sua resposta para aqueles que podem querer isso:

Nota: cell.disclosureIndicatorColor tem de ser definido após cell.accessoryType = .DisclosureIndicator é definido para que o botão disclosureIndicator está disponível em subviews da célula:

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

Alterar a cor da tonalidade da célula de exibição de tabela. Verifique a imagem para fazer o mesmo através de Storyboard

Como uma contribuição para a solução de @benzado I swiftified seu código como a seguir:

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

Com uma mudança da cor aplicativo uma chamada para setNeedsDisplay () no UITableCellView irá atualizar a cor. Eu gostaria de evitar o uso de objetos UIImage em vista celulares.

Uma versão rápida 3 dos CocoaNetics solução

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()
        }
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top