如何在 iOS SDK 中禁用 UIView/UIViewController 的“突出显示子视图”消息?

Posted

技术标签:

【中文标题】如何在 iOS SDK 中禁用 UIView/UIViewController 的“突出显示子视图”消息?【英文标题】:How to disable "highlight subviews" message for UIView/UIViewController in iOS SDK? 【发布时间】:2011-09-19 01:01:57 【问题描述】:

我想在点击UITableViewCell 时使用默认突出显示。但是,我不希望自定义子视图(及其子视图)收到消息以更新其突出显示的状态,从而破坏 backgroundColor 属性。

编辑 “子视图”是指任何 UIView 子类,而不仅仅是 UITableViewCells。

也许这种假设情况更能说明我在寻找什么:我有一个 UITableViewCell。称之为 c。然后我添加一个 UIView(称为 v)作为 c 的子视图。当我点击 c 时,我希望 c 突出显示(标准的蓝色背景和白色字体颜色),但是我不希望 v 突出显示。我该如何做到这一点?

【问题讨论】:

bump 我也很想知道一种方法! 对于那些已经或将要回复/回复有关将UITableViewCellSelectionStyle 设置为UITableViewCellSelectionStyleNone 的答案的人,这不起作用! 请仔细阅读题。谢谢。 这个问题的标题应该是:如何禁用 UITableViewCell 子视图在选择时自动突出显示。当前标题具有误导性。 【参考方案1】:

首先,UITableView 枚举所有子视图,并向它们发送高亮消息。

因此,即使您在视图中放置了一个 UILabel,无论它有多深,它都会遍历所有视图(通过使用 subviews 属性)。

一种解决方案可以是(也就是ios4+),覆盖subviews属性,并欺骗tableview的高亮功能,我们没有任何子视图。为此,我们需要确定调用者,如果它是 tableview 的 highlight 方法,我们应该根本不返回子视图。

我们可以创建一个简单的 UIView 子类并覆盖 subviews,如下所示。

- (NSArray *)subviews
    NSString* backtrace = [NSString stringWithFormat: @"%@",[NSThread callStackSymbols]];
    if ([backtrace rangeOfString:@"_updateHighlightColorsForView"].location!=NSNotFound)
        return [super subviews];   

    return [[NSArray new] autorelease];

callStackSymbols IOS4+后可用 _updateHighlightColorsForView是UITableView的方法,负责高亮所有children

【讨论】:

哇,太疯狂了。我不知道你能做到。不过听起来太老套了。 jason,是的,这是个骗子 :) 由于 tableview 解析所有视图层次结构,并向每个视图发送一条消息,我想这是唯一的方法 如果 UITableView 的内部结构发生变化,肯定会让自己崩溃——尽管我认为这不太可能,但肯定可以快速解决您的问题,尽管 不要做这个答案描述的事情。只需在创建 UITableViewCell 时将 selectionStyle 设置为 UITableViewCellSelectionStyleNone。您将不得不做自己的选择样式,但这应该很简单,只需覆盖 UITableViewCell 子类上的 setSelected 并调整子视图选择状态。 这个答案绝对糟糕。【参考方案2】:

我有一个继承自 UITableViewCell 的类,因此我将其修复为覆盖 setSelected:animated,如下所示:

   - (void)setSelected:(BOOL)selected animated:(BOOL)animated
   
       [super setSelected:selected animated:animated]; 
       //Reset highlighted status to all the childs that i care for.
       [self.someChild setHighlighted:NO];
       [self.someOtherChild setHighlighted:NO];
   

【讨论】:

如果您没有对单元格进行太多自定义并且想要除了几个关键子视图之外的默认 UITableViewCellSelectionStyle 行为,这是一个合理的解决方案。 我想这就是提问者想要的。 我想喜欢这个解决方案,但是在使用它时,子视图仍然会突出显示几分之一秒。它非常快,但它就在那里。【参考方案3】:

我通过像这样覆盖-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated 解决了这个问题(仅当子视图是 UIControl 的子类时才有效):

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated 

    BOOL subviewWasEnabled = mySubview.enabled; //check if the view is enabled
    mySubview.enabled = NO; //disable it anyways

    [super setHighlighted:highlighted animated:animated];

    mySubview.enabled = subviewWasEnabled; //enable it again (if it was enabled)

【讨论】:

这是一个很好的解决方案。谢谢。【参考方案4】:

在表格单元格上使用 UITableViewCellSelectionStyleNone。

见the apple API documentation。

【讨论】:

这是在选择表格单元格时关闭子视图自动突出显示的正确方法。您显然现在必须进行自己的行选择样式。但这很容易。 但这不是提问者想要的答案。他们想要几乎默认的选择/突出显示行为。【参考方案5】:

最近我一直在寻找相同的方法,但老实说我找不到以编程方式执行此操作的方法,所以我有点作弊了。

由于突出显示图像,我最终使用UIImageView 填充了我的UIView 的整个框架,并为其分配了一个空白图像,然后在UIImageView 上方绘制了视图的其余部分。 您的UIView 仍会突出显示,但您将无法看到它,因为上面会有一张空白图片!

我希望这会有所帮助,我知道这可能不是最好的方法,但得到了我需要的结果

【讨论】:

【参考方案6】:

在您的 UIControl 子类中覆盖 -(void)setHighlighted:(BOOL)highlight; 方法,使其不执行任何操作。对于UIButton 子类,您可以这样做:

- (void)setHighlighted:(BOOL)highlighted 
    return;

【讨论】:

请注意,您可能还应该覆盖 setHighlighted:animated:。【参考方案7】:

我不想突出显示任何子视图。我的解决方案是将 selectionstyle 设置为 UITableViewCellSelectionStyleNone 并模仿默认选择行为如下(在 UITableViewCell 的自定义子类上覆盖 setSelected):

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

    int backgroundViewTag = 888;
    UIView *backgroundView = [self viewWithTag:backgroundViewTag];

    if (selected) 
        if (!backgroundView) 
            backgroundView = [[[UIView alloc] initWithFrame:self.bounds] autorelease];
            backgroundView.tag = backgroundViewTag;
            backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
            backgroundView.backgroundColor = [UIColor blueColor];
            backgroundView.alpha = 0.0;
            [self insertSubview:backgroundView atIndex:0];
        

        if (animated) 
            [UIView animateWithDuration:0.5 animations:^
                backgroundView.alpha = 1.0;
            ];
         else 
            backgroundView.alpha = 1.0;
        
     else if (backgroundView) 
        if (animated) 
            [UIView animateWithDuration:0.5 animations:^
                backgroundView.alpha = 0.0;
             completion:^(BOOL finished) 
            ];
         else 
            backgroundView.alpha = 0.0;
        
    
    [super setSelected:selected animated:animated];

【讨论】:

【参考方案8】:

也许我们可以改变子视图的高亮状态以匹配它们的默认视图。

这样,即使它更改为突出显示状态,它也会看起来处于默认状态。

不确定它是否有效,你能描述一下子视图吗?

【讨论】:

【参考方案9】:

我认为您需要禁用子视图(可能不需要)或子类化子视图以覆盖此行为。

【讨论】:

【参考方案10】:

也许如果您将子视图子类化并覆盖 setHighlighted 方法以不执行任何操作或覆盖突出显示的方法以始终返回 NO。

但是 UIView 没有高亮状态,你添加什么样的 UIView 子元素到你的单元格?

【讨论】:

【参考方案11】:

所以也许是这样的:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath 
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

m_colors = [[NSMutableArray alloc] init];

for (UIView *view in [cell.contentView subviews]) 
    [m_colors addObject:view.backgroundColor];


return indexPath;


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

for (int x = 0; x < [m_colors count]; ++x) 
    [[[cell.contentView subviews] objectAtIndex:x] setBackgroundColor:[m_colors objectAtIndex:x]];


[m_colors release];
m_colors = nil;

【讨论】:

【参考方案12】:

只需将您的视图放在 UIButton 中,它们不会在突出显示时更新。您不能仅在 runtime 上使用情节提要的 xib 来做到这一点。

UIButton *button = [[UIButton alloc] initWithFrame:0, 0, cellWidth, cellHeight];
[button addSubview:anyView]; // This view don't change his background color
[cell addSubview:button];

【讨论】:

以上是关于如何在 iOS SDK 中禁用 UIView/UIViewController 的“突出显示子视图”消息?的主要内容,如果未能解决你的问题,请参考以下文章

在 Facebook IOS SDK 中禁用单点登录 (SSO)

iOS SDK 禁用内置麦克风

Pushwoosh iOS SDK,在后台模式下禁用 pushwoosh 生成的警报

如何使用 sdk 在设置应用程序中启用-禁用通知?

如何在 QuickBlox 中禁用日志语句?

iOS7,有没有办法在 UINavigationViewcontroller 中禁用 UIViewController 的过渡?