22

我需要更改disclosureIndicatorView附件的颜色UITableViewCell。我认为有两种方法可以完成这项工作,但我无法确定哪种方法是最佳的。所以这就是我认为我能做的。

有一个属性UITableViewCell- accessoryView。所以我可以使用setAccessoryView:(UIView *)view并传递视图作为UIImageView持有我想要的图像。

我编写了一个实用程序类,它为我的单元格创建内容视图(例如背景颜色、添加其他内容等),并将此内容视图添加到UITableViewDelegate. 另一种选择是绘制一个UIImage覆盖实用程序类的drawRect方法。CustomContentView

执行选项 1 - 我可以按照苹果的方式完成工作。只需给他们视图,其余的由他们完成。但我想UIView每行添加一个新对象可能会导致对象分配繁重并降低帧速率。与UIImage我的contentView. 我相信UIImageUIView.

请扔一些轻松的人,帮助我做出决定。

4

12 回答 12

29

关于 Cocoanetics 的好帖子解决了这个问题。UIControl 类继承了选定、启用和突出显示的自定义颜色披露指示器的属性

于 2011-04-05T17:33:07.313 回答
24

如果您对绘制指标感兴趣,而不是使用图像文件,请使用以下代码:

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

如果您创建自定义 UIView 子类,请在 drawRect: 方法中执行上述操作,并将其用作您的辅助视图,您将能够使颜色成为您想要的任何颜色。

只要您正确回收 UITableViewCell 实例,附件视图(自定义或 UIImageView 就不会成为主要的性能问题。

于 2010-01-04T01:53:28.833 回答
12

这是一个适用于 iOS 8+ 的实现。它完全符合要求:
将原始 Apple 披露指示器的颜色更改为自定义颜色。
像这样使用它:

#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
于 2016-02-16T08:40:04.900 回答
8

在 swift 3 中,我将@galambalazs 的解决方案改编为类扩展,如下所示:

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

希望这会有所帮助。

于 2017-02-27T12:31:45.930 回答
5

使用 UIImageView。这也将允许您在选择单元格时更改图像:

UIImageView* arrowView = [[UIImageView alloc] initWithImage:normalImage];
arrowView.highlightedImage = selectedImage;
cell.accessoryView = arrowView;
[arrowView release];
于 2012-07-06T15:09:40.667 回答
4

但我猜想向每一行添加一个新的 UIView 对象可能会导致大量的 obj 分配并降低帧速率。与我的 contentView 中的 UIImage 对象相比。我相信 UIImage 比 UIView 轻。

直接绘制图像几乎肯定会比添加子视图具有更好的性能。您必须确定是否需要额外的性能。我已经使用了一些辅助视图来自定义基本单元格的披露指标,并且性能很好。但是,如果您已经在为内容矩形进行自定义绘图,那么进行辅助视图也可能不是那么困难。

于 2009-12-06T06:16:56.910 回答
2

benzado 的解决方案工作正常,但它显示黑色背景。在您设置的 UIView 类中(您在他的代码中放置的 drawRect 函数)需要具有以下 initWithFrame 实现,以便公开绘图具有透明背景:

- (id)initWithFrame:(CGRect)frame {

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

当然,您可以将其设置为您想要的任何颜色...

于 2011-01-12T18:33:34.133 回答
1

虽然 galambalazs 的回答有效,但应该注意的是,它间接访问和更新了 Apple 对披露指标的私有实现,这在某种程度上是一种黑客行为。充其量,它可能会在未来的 iOS 版本中停止工作,最坏的情况是导致 App Store 被拒绝。在 Apple 公开用于直接设置颜色的属性之前,设置accessoryView仍然是被批准的方法。

无论如何,对于那些可能想要它的人来说,这是他的答案的 Swift 实现:

注意:cell.disclosureIndicatorColor必须在设置 cell.accessoryType = .DisclosureIndicator设置,以便在单元格的子视图中可以使用公开指示器按钮:

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
    }
}
于 2016-04-06T14:52:54.633 回答
1

在 iOS 13+ 中,显示指示器是通过非模板 UIImage 设置的,该 UIImage 由用户的暗模式偏好决定。由于图像是非模板化的,它不会尊重单元格的 tintColor 属性。换句话说,暗模式偏好具有最高优先级。如果您不想使用 iOS 派生的显示指示器,则必须使用自定义图像。

于 2019-12-04T10:08:00.883 回答
0

作为对@benzado 解决方案的贡献,我将他的代码简化如下:

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

随着应用程序颜色的更改,对 UITableCellView 上的 setNeedsDisplay() 的调用将更新颜色。我喜欢避免在单元格视图中使用 UIImage 对象。

于 2016-06-15T10:28:42.707 回答
0

一个 Swift 3 版本的 CocoaNetics解决方案

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()
        }
    }
}
于 2017-07-31T16:54:21.627 回答
-1

更改表格视图单元格的色调颜色。通过 Storyboard 检查屏幕截图以执行相同的操作。

于 2018-11-08T06:25:09.820 回答