Cual es la mejor manera de cambiar el color/vista de la divulgación indicador de accesorios de ver en una vista de tabla de células en iOS?

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

Pregunta

Necesito cambiar el color de la disclosureIndicatorView accesorio en un UITableViewCell.Creo que hay dos maneras para hacer esto, pero no soy capaz de averiguar cuál es el óptimo.Así que aquí es lo que yo pienso hacer.

Hay una propiedad de UITableViewCell - accessoryView.Por lo tanto puedo usar setAccessoryView:(UIView *)view y de paso ver como la UIImageView la celebración de la imagen que quiero.

He escrito una clase de utilidad que crea la vista del contenido (cosas como el color de fondo, añadiendo otras cosas, etc) para mi celular y me agregue a esta vista del contenido de la celda en la UITableViewDelegate.La otra opción es dibujar un UIImage la invalidación de la drawRect método de CustomContentView utilidad de la clase.

La realización de la opción 1 - puedo conseguir el hacer las cosas de la forma en que apple.Sólo les dan la vista y ellos hacen el resto.Pero supongo que la adición de un nuevo UIView objeto para cada fila puede llegar a ser un objeto pesado, la asignación y la disminución de la velocidad de fotogramas.En comparación a sólo una UIImage objeto en mi contentView.Creo UIImage es más ligero que el UIView.

Por favor, arrojar algo de luz a la gente y me ayude a decidir sobre él.

¿Fue útil?

Solución

  

Pero supongo que la adición de un nuevo objeto UIView a cada fila podría llegar a ser una asignación obj pesada y la disminución de la velocidad de fotogramas. En comparación con sólo un objeto UIImage en mi contentView. Creo que es más ligero que UIImage UIView.

Dibujo una imagen directamente casi seguro que tienen un mejor rendimiento que la adición de una vista secundaria. Usted tiene que determinar si es necesario que el rendimiento adicional. He usado un par de puntos de vista de accesorios para indicadores de divulgación personalizados en las células básicas y el rendimiento estaba bien. Sin embargo, si ya está haciendo dibujo para el rect contenido personalizado, puede que no sea tan difícil de hacer la vista accesorio también.

Otros consejos

Gran post en Cocoanetics que se ocupa de esto. La clase uicontrol hereda las propiedades seleccionadas, habilitado y destacaron personalizada coloreadas

Si está interesado en la elaboración del indicador, en lugar de utilizar un archivo de imagen, aquí está el código que funcionó para hacerlo:

// (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 usted hace una subclase UIView personalizado, haga lo anterior en el drawRect:. Método, y usar eso como su punto de vista accesorio, podrás hacer nada el color que desee

Una vista de accesorios (personalizado o UIImageView no será un problema mayor rendimiento siempre y cuando se está reciclando adecuadamente casos UITableViewCell.

Esta es una implementación que funciona en iOS 8 +. Hace exactamente lo que ha pedido:
cambiar el color del indicador original divulgación de Apple a un color personalizado.
 Utilizar de esta manera:

#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

en Swift 3, He adaptado la solución de @galambalazs como una extensión de la clase como sigue:

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 esto ayude un poco.

Utilice un UIImageView. Esto también le permitirá cambiar la imagen cuando se selecciona la celda:

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

La solución de benzado funciona bien, pero mostró un fondo negro. En la clase UIView que la configuración (el que está drawRect función se pone en su código) necesita tener la siguiente implementación initWithFrame a fin de que la divulgación de dibujo para tener un fondo transparente:

- (id)initWithFrame:(CGRect)frame {

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

Por supuesto, se puede establecer esto en cualquier color que desee ...

Mientras respuesta galambalazs' funciona, hay que señalar que se trata de algo así como un truco, ya que indirectamente accesos y actualizaciones de la aplicación privada de Apple en el indicador de la divulgación. A lo sumo, podría dejar de trabajar en las futuras versiones de iOS, y en el peor lugar al rechazo App Store. Ajuste de la accessoryView sigue siendo el método aprobado hasta que Apple expone una propiedad para establecer directamente el color.

En cualquier caso, aquí es la rápida aplicación de su respuesta para aquellos que quieran que:

Nota: cell.disclosureIndicatorColor tiene que ser establecido después cell.accessoryType = .DisclosureIndicator se ajusta de manera que el botón disclosureIndicator está disponible en subvistas de la 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
    }
}

Cambiar el color de la tinta de la célula vista de tabla. Compruebe la pantalla para hacer lo mismo a través de Storyboard

Como una contribución a la solución de @benzado I swiftified su código como sigue:

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 cambio de color de la aplicación de una llamada a setNeedsDisplay () en el UITableCellView actualizará el color. Me gustaría evitar el uso de objetos en vistas UIImage celulares.

A SWIFT versión 3 de los CocoaNetics solución

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top