在" editActionsForRowAtIndexPath"中使用UITableViewRowAction方法。我可以更改UITableViewRowAction的backgroundcolor,但无法更改标题颜色。但我想改变UITableViewRowAction的颜色。关于这方面的任何意见都会很明显。
答案 0 :(得分:18)
有一种方法可以实现您的目标。但这有点棘手。
结果示例:
这个技巧的想法是你可以实际修改背景颜色。这意味着您可以设置UIColor的+ colorWithPatternImage:并设置与所需样式匹配的位图图像。这可以通过使用图形编辑器创建图像或使用例如Core Graphics渲染来实现。此解决方案的唯一问题是,您必须使用特定的文本属性模仿原始标题长度才能使其正常工作,并且还必须将表视图行操作的标题设置为空格字符串,以便表视图单元格准备足够空间为您“自定义操作按钮”。如果使用可变单元格行,在photoshop中创建静态png资产可能不合适。
这是NSString的类别,它创建一个空格的字符串,为您的自定义按钮创建空间,第二个将生成将作为背景图案图像放置的位图图像。对于参数,您必须为原始标题设置文本属性,基本上是@{NSFontAttributeName: [UIFont systemFontOfSize:18]}
,而不是您想要的文本属性。也许有更好的方法来实现这一点:)
@implementation NSString (WhiteSpace)
- (NSString *)whitespaceReplacementWithSystemAttributes:(NSDictionary *)systemAttributes newAttributes:(NSDictionary *)newAttributes
{
NSString *stringTitle = self;
NSMutableString *stringTitleWS = [[NSMutableString alloc] initWithString:@""];
CGFloat diff = 0;
CGSize stringTitleSize = [stringTitle sizeWithAttributes:newAttributes];
CGSize stringTitleWSSize;
NSDictionary *originalAttributes = systemAttributes;
do {
[stringTitleWS appendString:@" "];
stringTitleWSSize = [stringTitleWS sizeWithAttributes:originalAttributes];
diff = (stringTitleSize.width - stringTitleWSSize.width);
if (diff <= 1.5) {
break;
}
}
while (diff > 0);
return [stringTitleWS copy];
}
@end
第二个重要的部分是渲染位图的代码,该位图可以用作UITableViewRowAction的backgroundColor的模式图像。
- (UIImage *)imageForTableViewRowActionWithTitle:(NSString *)title textAttributes:(NSDictionary *)attributes backgroundColor:(UIColor *)color cellHeight:(CGFloat)cellHeight
{
NSString *titleString = title;
NSDictionary *originalAttributes = @{NSFontAttributeName: [UIFont systemFontOfSize:18]};
CGSize originalSize = [titleString sizeWithAttributes:originalAttributes];
CGSize newSize = CGSizeMake(originalSize.width + kSystemTextPadding + kSystemTextPadding, originalSize.height);
CGRect drawingRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, cellHeight));
UIGraphicsBeginImageContextWithOptions(drawingRect.size, YES, [UIScreen mainScreen].nativeScale);
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(contextRef, color.CGColor);
CGContextFillRect(contextRef, drawingRect);
UILabel *label = [[UILabel alloc] initWithFrame:drawingRect];
label.textAlignment = NSTextAlignmentCenter;
label.attributedText = [[NSAttributedString alloc] initWithString:title attributes:attributes];
[label drawTextInRect:drawingRect];
//This is other way how to render string
// CGSize size = [titleString sizeWithAttributes:attributes];
// CGFloat x = (drawingRect.size.width - size.width)/2;
// CGFloat y = (drawingRect.size.height - size.height)/2;
// drawingRect.origin = CGPointMake(x, y);
// [titleString drawInRect:drawingRect withAttributes:attributes];
UIImage *returningImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return returningImage;
}
然后当您创建行动时,您可以执行以下操作:
NSDictionary *systemAttributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:18] };
NSDictionary *newAttributes = @{NSFontAttributeName: [UIFont fontWithName:@"Any font" size:15]};
NSString *actionTitle = @"Delete";
NSString *titleWhiteSpaced = [actionTitle whitespaceReplacementWithSystemAttributes:systemTextFontAttributes newAttributes:newAttributes];
UITableViewRowAction *rowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:titleWhiteSpaced handle:NULL];
UIImage *patternImage = [self imageForTableViewRowActionWithTitle:actionTitle textAttributes:newAttributes backgroundColor:[UIColor redColor] cellHeight:50];
rowAction.backgroundColor = [UIColor colorWithPatternImage:patternImage];
这个解决方案显然很容易,但你可以在不使用私有API的情况下达到预期的效果,并且将来如果出现问题,这不会破坏你的应用程序。只有按钮看起来不合适。
结果示例:
这段代码当然有很多改进的空间,任何建议都值得赞赏。
答案 1 :(得分:10)
夫特
无需乱搞UIButton.appearance ...
将它放在您的单元格类中,并根据您的需要更改UITableViewCellActionButton。
override func layoutSubviews() {
super.layoutSubviews()
for subview in self.subviews {
for subview2 in subview.subviews {
if (String(subview2).rangeOfString("UITableViewCellActionButton") != nil) {
for view in subview2.subviews {
if (String(view).rangeOfString("UIButtonLabel") != nil) {
if let label = view as? UILabel {
label.textColor = YOUR COLOUR
}
}
}
}
}
}
}
答案 2 :(得分:8)
我担心无法更改UITableViewRowAction的标题颜色。
您可以在行动中改变的唯一事项是:
有关详细信息,请参阅Apple Doc UITableViewRowAction
答案 3 :(得分:6)
确实有一种方法可以更改UITableViewRowAction的标题颜色。这是一个按钮。您可以使用UIButton
外观代理:
[[UIButton appearance] setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
答案 4 :(得分:5)
Lee Andrew's answer Swift 3 / Swift 4 :
class MyCell: UITableViewCell {
override func layoutSubviews() {
super.layoutSubviews()
for subview in self.subviews {
for sub in subview.subviews {
if String(describing: sub).range(of: "UITableViewCellActionButton") != nil {
for view in sub.subviews {
if String(describing: view).range(of: "UIButtonLabel") != nil {
if let label = view as? UILabel {
label.textColor = UIColor.black
}
}
}
}
}
}
}
}
答案 5 :(得分:3)
因此,在 iOS 13 天之内,仍然没有公共API可以将textColor
或font
更改为单元格操作。
线程中的答案导致的结果非常不可靠,但是我设法使我的hack版本正常工作。
这是我访问操作UILabel
的简化方法:
extension UITableViewCell {
var cellActionButtonLabel: UILabel? {
superview?.subviews
.filter { String(describing: $0).range(of: "UISwipeActionPullView") != nil }
.flatMap { $0.subviews }
.filter { String(describing: $0).range(of: "UISwipeActionStandardButton") != nil }
.flatMap { $0.subviews }
.compactMap { $0 as? UILabel }.first
}
}
接下来,在我的layoutSubviews()
子类中重写UITableViewCell
是不够的,因此我还必须重写layoutIfNeeded()
才能使该黑客工作。
请注意,同时覆盖它们很重要!
override func layoutSubviews() {
super.layoutSubviews()
cellActionButtonLabel?.textColor = .black // you color goes here
}
override func layoutIfNeeded() {
super.layoutIfNeeded()
cellActionButtonLabel?.textColor = .black // you color goes here
}
难题的最后一步是安排颜色的额外刷新,因此我们介绍了由于某些原因而无法调用上述函数的所有情况。这样做的最佳位置是UITableViewDelegate
方法..., willBeginEditingRowAt: ...
func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
tableView.cellForRow(at: indexPath)?.layoutIfNeeded()
}
}
延迟的布局刷新触发器具有让UIKit首先配置单元的技巧,因此我们可以在自定义之后立即跳转。 0.01
对我来说足够了,但我可能因情况而异。
现在,您可以根据需要自定义标签!更改文本,颜色,字体或添加子视图!
毋庸置疑,如果Apple决定更改其私有实现,这随时可能中断。
答案 6 :(得分:2)
iOS 11 解决方案:
像这样创建UITableViewCell
扩展名:
extension UITableViewCell {
/// Returns label of cell action button.
///
/// Use this property to set cell action button label color.
var cellActionButtonLabel: UILabel? {
for subview in self.superview?.subviews ?? [] {
if String(describing: subview).range(of: "UISwipeActionPullView") != nil {
for view in subview.subviews {
if String(describing: view).range(of: "UISwipeActionStandardButton") != nil {
for sub in view.subviews {
if let label = sub as? UILabel {
return label
}
}
}
}
}
}
return nil
}
}
并在UITableViewCell
override func layoutSubviews() {
super.layoutSubviews()
cellActionButtonLabel?.textColor = .red
}
但是有一个错误 - 如果你快速拉动单元格,这段代码有时不会改变颜色。
答案 7 :(得分:1)
您可以在UITableViewCell
子类中添加这两个函数,并调用setActionButtonsTitleColor
函数来设置操作按钮的标题颜色。
func setActionButtonsTitleColor(color: UIColor) {
let actionButtons: [UIButton] = self.getActionButtons()
for actionButton in actionButtons {
actionButton.setTitleColor(color, for: .normal)
}
}
func getActionButtons() -> [UIButton] {
let actionButtons: [UIButton] = self.subviews.map {
(view: UIView) -> [UIView] in
return view.subviews
}
.joined()
.filter {
(view: UIView) -> Bool in
return String(describing: view).contains("UITableViewCellActionButton")
}.flatMap {
(view: UIView) -> UIButton? in
return view as? UIButton
}
return actionButtons
}
答案 8 :(得分:0)
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewRowAction *editAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"edit" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
// Action something here
}];
editAction.backgroundColor = [UIColor whiteColor];
[[UIButton appearance] setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
return @[editAction];
答案 9 :(得分:0)
如果有人仍在寻找替代解决方案:
您可以使用swipecellkit窗格
https://github.com/SwipeCellKit/SwipeCellKit
这使您可以自定义标签颜色,图像颜色甚至整个背景,同时保留本机实现的实际外观。