UISegmentedControl 不会取消选择旧段

Posted

技术标签:

【中文标题】UISegmentedControl 不会取消选择旧段【英文标题】:UISegmentedControl Doesn't Deselect Old Segment 【发布时间】:2014-10-25 22:12:40 【问题描述】:

我在 UITableView 表行中有一个 UISegmentedControl。选择触发,新的段被突出显示。问题是,旧段仍处于选中状态。

如果我关闭并重新打开包含表格的弹出框,则会显示正确的段索引。

我正在运行 XCode 6.1 并在 ios 7.1 模拟器上进行测试。

感谢您的帮助。

UITableViewCell *segmentCell = [tableView dequeueReusableCellWithIdentifier:segmentCellIdentifier];
if (segmentCell == nil) 
segmentCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:segmentCellIdentifier];
    
segmentCell.backgroundColor = [UIColor clearColor];
segmentCell.backgroundView = nil;
NSArray *segmentItems = [NSArray arrayWithObjects: NSLocalizedString(@"settingsBackgroundCork", @"Cork - Select cork background theme"), NSLocalizedString(@"settingsBackgroundDark", @"Dark - Select dark background theme"), NSLocalizedString(@"settingsBackgroundLight", @"Light - Select light background theme"), nil];
self.backgroundSegmentedControl = [[UISegmentedControl alloc] initWithItems: segmentItems];
[self.backgroundSegmentedControl addTarget:self action:@selector(backgroundControlChanged:) forControlEvents: UIControlEventValueChanged];
self.backgroundSegmentedControl.frame = CGRectMake(10, 6, 300, 32);
NSInteger background = [[NSUserDefaults standardUserDefaults] integerForKey:kUserDefaultsBackgroundSelection];
self.backgroundSegmentedControl.selectedSegmentIndex = background;
self.backgroundSegmentedControl.momentary = NO;
[segmentCell.contentView addSubview:self.backgroundSegmentedControl];
cellToReturn = segmentCell;

这是在段选择时调用的方法:

- (void)backgroundControlChanged:(UISegmentedControl *)control

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger:control.selectedSegmentIndex forKey:kUserDefaultsBackgroundSelection];
self.backgroundSegmentedControl.selectedSegmentIndex = control.selectedSegmentIndex;
[self.backgroundSegmentedControl setNeedsDisplay];
[[NSNotificationCenter defaultCenter] postNotificationName:kPageBackgroundShouldChangeNotification object:nil];

【问题讨论】:

您的表格视图是否滚动,如果是,您是否只有在滚动后才能看到这种效果? tableview 可以滚动。也就是说,该元素位于顶部,并且无需滚动即可显示。测试时我没有滚动(即没有重绘行)。 我可以复制您的问题的唯一方法是滚动。您的代码存在的一个问题是,当您重用一个单元格时,您将在旧控制器之上添加新的分段控制器。最好创建一个子类单元格,并在其 init 方法中添加分段控件。或者,您可以在将单元格添加到 cellFroRowAtIndexPath 之前检查单元格是否包含分段控件。 我遇到了同样奇怪的问题。如果我将分段控件的创建放在 dispatch_async(dispatch_get_main_queue(), ^) 块中,结果会有所不同,但它仍然不能正确运行。我完全从头开始制作类似的控件。这确实是一个奇怪的问题。 【参考方案1】:

奇怪的错误 - 我以前从未见过这个。两个建议:

尝试在处理程序中再次设置selectedSegmentIndex,然后 尝试在那里的控件上调用setNeedsDisplay

momentary默认为NO,所以不需要设置。

另外,在selectedSegmentIndex 文档中它说:

默认值是 UISegmentedControlNoSegment (没有选择段),直到用户触摸一个段。将此属性设置为 -1 以关闭当前选择。

也许你也想试试这最后一件事。

【讨论】:

感谢您的建议。我已经尝试了您的前 2 个建议,但无济于事。更新了上面的代码示例。我也试过你的 -1 来关闭选择,但是分段控件根本没有注册选择。【参考方案2】:

我能够通过将我对 setSelectedSegmentIndex 的调用移至 setNeedsLayout 函数内部来解决此问题,而不是在创建 UISegmentedControl 后立即调用它。当然,我还必须创建一个变量来跟踪应该选择哪个段。

【讨论】:

【参考方案3】:

有同样的问题。通过在添加新实例之前从 superview 中删除 segmentedControl 的前一个实例来解决它。

在将 segmentedControl 的新实例添加到父视图之前,添加下面提到的 3 行代码以删除先前的 segmentedControl。

self.backgroundSegmentedControl.tag = 101
if let foundView2 = segmentCell.contentView.viewWithTag(101) 
    foundView2.removeFromSuperview()

[segmentCell.contentView addSubview:self.backgroundSegmentedControl];

【讨论】:

以上是关于UISegmentedControl 不会取消选择旧段的主要内容,如果未能解决你的问题,请参考以下文章

UISegmentedControl选择状态图标图像

如何检查用户是不是选择了 UISegmentedControl?

UISegmentedControl 在值更改时未选择

使用 UISegmentedControl 发送的无法识别的选择器

选择 UISegmentedControl 控件会导致 SIGABRT

从 UITableView didSelectRowAtIndexPath 检测 UISegmentedControl 中的选择更改