UITableViewCell 在取消选择时选择了阴影颜色

Posted

技术标签:

【中文标题】UITableViewCell 在取消选择时选择了阴影颜色【英文标题】:UITableViewCell selected shadow color on deselection 【发布时间】:2012-10-24 17:52:03 【问题描述】:

我有一个标准的 UITableView。我想将单元格的textLabelshadowColor 设置为[UIColor whiteColor],但仅在触摸单元格时。为此,我使用以下代码。它是一个自定义 UITableViewCell 子类,它覆盖了 setSelected/setHighlighted:

@implementation ExampleTableViewCell


- (void)setSelected:(BOOL)selected animated:(BOOL)animated

    [super setSelected:selected animated:animated];
    [self setShadowColorSelected:selected];



- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated 
    [super setHighlighted:highlighted animated:animated];
    [self setShadowColorSelected:highlighted];


- (void)setShadowColorSelected:(BOOL)selected 
    if (selected) 
        self.textLabel.shadowColor = [UIColor blackColor];
    else 
        self.textLabel.shadowColor = [UIColor whiteColor];
    


@end

我对这种方法的问题是,在取消选择时,单元格的时间很短,标签的文本和阴影都是白色的。请看这个截图,它是在取消选择:

这与这两个帖子中的方法基本相同:

UILabel shadow from custom cell selected color

Removing text shadow in UITableViewCell when it's selected

我在后一个问题中使用了接受答案的方法。

我创建了一个非常简单的代码项目和uploaded it to github。它显示了我的问题。它只是一个显示单个单元格的 UITableViewController。

除此之外,没有什么花哨的。 UITableView 委托方法:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell) 
        cell = [[ExampleTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    
    cell.textLabel.text = @"test";

    return cell;


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; //setting this to NO doesn't work either!

有什么想法吗?

【问题讨论】:

我只是在这里大声思考,但是您是否尝试过在setSelectedsetHighlighted(其中之一)中设置条件,以便仅在@ 时调用setShadowColorSelected 987654333@ 的值是true?这两种方法中的一种可能在另一种方法之前被调用,这就是为什么阴影在高光被移除之前变成白色的原因。 好吧,我尝试了类似的方法,它只实现了其中一种方法,所以要么setSelected要么setHighlighted。导致相同的问题。 我不知道这里有什么问题,这种行为对我来说似乎是正确的。你不会指望setHighlighted:setSelected: 在动画完成之前阻塞线程,是吗? 不,我不知道。问题是,在上面的屏幕截图中,shadowColor 是白色的(这意味着 setSelected/setHighlighted 已在单元格上调用了 NO),但 UILabel's textColor 也是白色的,这是它的 @ 987654342@。所以标签仍然处于“突出显示”状态,但单元格不是。 既然您知道您的方法是用NO 调用的,那么也许您也可以尝试在您的setShadowColorSelected 方法中将self.textLabel.textColor 设置为白色/黑色? 【参考方案1】:

如果我理解了这个问题,您需要显示阴影颜色,直到单元格选择动画消失。我不确定您尝试的方式有什么不正确,但更直接的解决方案可以正常工作。

请注意,一旦不需要观察者,您就需要将其移除。

ExampleTableViewCell.h

@interface ExampleTableViewCell : UITableViewCell 



- (void) setSelectionShadowOfColor:(UIColor *) selColor;
@end

ExampleTableViewCell.m

@implementation ExampleTableViewCell

- (void) setSelectionShadowOfColor:(UIColor *) selColor 
    self.textLabel
    [self addObserver:self
           forKeyPath:@"textLabel.highlighted" // not isHighlighted as that is a getter name of the highlighted property
              options:NSKeyValueObservingOptionNew
              context:NULL];



- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context 

    BOOL isHighlighted = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];

    if (isHighlighted) 
        self.textLabel.shadowColor = [UIColor blackColor];
     else 
        self.textLabel.shadowColor = [UIColor whiteColor];
    


@end

ExampleTableViewController.m

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *CellIdentifier = @"Cell";
    ExampleTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; // note the type ExampleTableViewCell is used here to avoid the interface lookup mess
    if (!cell) 
        cell = [[ExampleTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        [cell setSelectionShadowOfColor:[UIColor blackColor]];
    
    cell.textLabel.text = @"test";

    return cell;

【讨论】:

是的!就是这样。我考虑过 KVO-ing 标签的 highlighted 属性,但我认为这太过分了。但它实际上是迄今为止唯一有效的答案。在我接受你的回答并请艾伦将赏金奖励给你之前,我会等一下,看看是否有人想出了更好的东西。 我完全同意你的看法,如果有更好的(或其他可行的)解决方案,请在评论中通过@A-Live 告诉我。 你将如何在 Swift 2.2 中做到这一点?有没有类似的方法? 我看不到在 swift 中使用相同方法的任何问题,你有什么特别的问题吗,@blackjacx? 是的,很抱歉,它在 Swift 中是可能的。抱歉,我在提问后读到了这一点;-)【参考方案2】:

将以下内容添加到您的 UITableViewDelegate:

NSIndexPath *selectedIndex;

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell) 
        cell = [[ExampleTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    
    cell.textLabel.text = @"test";
    if(indexpath == selectedIndex)
    
        cell.textlabel.shadowColor = [UIColor blackColor];
    
    else
    
        cell.textlabel.shadowColor = [UIColor whiteColor];
    
    return cell;


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    [self.tableView beginUpdates];
    selectedIndex = indexpath;
    [self.tableView endUpdates];

【讨论】:

抱歉,这应该如何工作? cellForRowAtIndexPath 甚至不会在选择时调用。 对不起,我忘了更新UITableView,检查编辑的答案,它现在应该可以工作了:) 好的,是的,这可能确实有效,但我不想在每次选择时更新整个 tableView。【参考方案3】:

这是我能做到的最好的:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated

    [super setSelected:selected animated:NO];

    [self setShadowColorSelected:selected];


- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated 
    [super setHighlighted:highlighted animated:YES];

    [self setShadowColorSelected:highlighted];


- (void)setShadowColorSelected:(BOOL)selected 
    [self.textLabel setBackgroundColor:[UIColor clearColor]];

    if (selected)
    
        [self.textLabel setTextColor:[UIColor whiteColor]];
        [self.textLabel setShadowColor:[UIColor blackColor]];

        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView transitionWithView:self.textLabel duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^
            if (selected)
            
                [self.textLabel setTextColor:[UIColor whiteColor]];
                [self.textLabel setShadowColor:[UIColor blackColor]];
            
            else
            
                [self.textLabel setTextColor:[UIColor blackColor]];
                [self.textLabel setShadowColor:[UIColor whiteColor]];
            
         completion:nil];
    
    else
    
         [self.textLabel setTextColor:[UIColor blackColor]];
         [self.textLabel setShadowColor:[UIColor whiteColor]];
    

【讨论】:

谢谢,您的回答有点用,但是在非动画取消选择时看起来不太好(调用[self.tableView deselectRowAtIndexPath:indexPath animated:NO]; 时)。必须有更好的方法来解决这个问题,这是很常见的事情。【参考方案4】:

这里有一个简单的方法来完成你想要的:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 

    self.textLabel.shadowColor = [UIColor blackColor];
    [super touchesBegan:touches withEvent:event];

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 

    self.textLabel.shadowColor = [UIColor whiteColor];
    [super touchesEnded:touches withEvent:event];

-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 

    self.textLabel.shadowColor = [UIColor whiteColor];
    [super touchesCancelled:touches withEvent:event];

【讨论】:

谢谢,我试过了,但不幸的是它并没有解决问题。此外,仅仅为此重写事件处理代码也不是很优雅,在某些情况下可能会导致问题。使用这种方法,您将在哪里/以哪种方法将阴影设置回 whiteColor?使用您发布的代码,即使取消选择它也会保持黑色。 我把你想要的颜色倒过来了。现在解决了。如果您尝试该代码,您会发现它有效。当调用 touchesEnded 或 touchesCancelled 时,shadowColor 被设置回原来的颜色。 刚试过,不行。给出完全相同的结果,我可以使用您的代码生成与上面相同的屏幕截图:( 仔细看,当您放开单元格时,它只有一帧。【参考方案5】:

我猜你应该需要为文本/阴影颜色的变化设置动画,其持续时间与 UITableView 用于动画选择/取消选择的持续时间相同。在我的理解中,你在 tableView 开始 动画选择突出显示的(dis)出现的确切时刻更改文本/阴影颜色,所以你得到的是你的颜色会瞬间改变,而选择突出显示需要一些时间才能从一种状态动画到另一种状态

试试这样的:

__block UIColor *newShadowColor = selected ? [UIColor blackColor] : [UIColor whiteColor];
[UIView animateWithDuration:0.2
                 animations:^
                        /* change your label/shadow color here. */
                        self.textLabel.shadowColor = newShadowColor;
                 
                 completion:^(BOOL finished)
                       /* this is where the cell is no longer selected
                          or highlighted. You may do some additional style changes to your
                          label here */ ];

【讨论】:

像 Rick Pastoor 的另一个答案一样,在非动画取消选择上不起作用。 好吧,只要在 -setSelected:animated: 中设置 animationDuration 为 0 if animated==NO 如果我将 animationDuration 设置为 0,这与我的代码有何不同?我可以制作相同的屏幕截图,不是吗?【参考方案6】:

我有同样的问题。我查看的所有解决方案都需要 subcassing / 过多的附加代码。

我最后所做的是在主UILabel 下方创建第二个UILabel 以充当阴影。

不要在主标签和阴影标签上设置阴影。对于阴影标签,将“正常颜色”设置为您想要的阴影颜色,并将突出显示的颜色设置为“清除颜色”。

显然,每次更新主标签时,您都必须更新影子标签。在很多情况下,付出的代价并不大。

希望有帮助!

【讨论】:

嗯,是的,我可以看到这可以工作,但对于这样一个简单的事情来说似乎真的需要做很多工作。我更喜欢 A-Live 的 KVO 解决方案。【参考方案7】:

据我了解,您可以通过使用以下代码和所需颜色更改表格视图的颜色来消除此问题

[tableView setBackgroundColor:[UIColor "GrayColor"]];

【讨论】:

【参考方案8】:

我也遇到了同样的问题。

您可以使用 UIButton 而不是使用默认标签,您的问题将得到解决。

将自定义按钮放入单元格中。

我的要求得到了解决。它可能会对你有所帮助。

【讨论】:

以上是关于UITableViewCell 在取消选择时选择了阴影颜色的主要内容,如果未能解决你的问题,请参考以下文章

自定义 UITableViewCell 标签文本在取消选择时不会变回

显示 UIMenuController 取消选择 UITableViewCell

关闭 UIMenuController 后如何取消选择 UITableViewCell?

带有 canBecomeFirstResponder YES 的自定义 UITableViewCell 不会在屏幕外取消选择

Swift 在 UITableViewCell 内的 UICollectionView 的单选/多选模式下进行选择/取消选择

当您向上或向下滚动时,选择一个 UITableViewCell 会选择同一位置的其他单元格