你如何让 UIPickerView 组件环绕?

Posted

技术标签:

【中文标题】你如何让 UIPickerView 组件环绕?【英文标题】:How do you make an UIPickerView component wrap around? 【发布时间】:2008-10-18 02:41:10 【问题描述】:

我想在 UIPickerView 组件中显示一组连续的数字,但让它像 Clock->Timer 应用程序的秒组件一样环绕。我可以启用的唯一行为类似于 Timer 应用程序的小时组件,您只能在其中向一个方向滚动。

【问题讨论】:

【参考方案1】:

将行数设置为大数字同样容易,并使其以较高的值开始,用户滚动滚轮很长时间的可能性很小——即使这样,更糟糕的是,他们会触底。

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component 
    // Near-infinite number of rows.
    return NSIntegerMax;


- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component 
    // Row n is same as row (n modulo numberItems).
    return [NSString stringWithFormat:@"%d", row % numberItems];


- (void)viewDidLoad 
    [super viewDidLoad];

    self.pickerView = [[[UIPickerView alloc] initWithFrame:CGRectZero] autorelease];
    // ...set pickerView properties... Look at Apple's UICatalog sample code for a good example.
    // Set current row to a large value (adjusted to current value if needed).
    [pickerView selectRow:currentValue+100000 inComponent:0 animated:NO];
    [self.view addSubview:pickerView];


- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component 
    NSInteger actualRow = row % numberItems;
    // ...

【讨论】:

这就是时钟应用程序实现“循环”的方式。NSIntegerMax NSIntegerMax 可能不是明智之举。 NSIntegerMax 取决于平台。它使 Lion 上的模拟器崩溃(其中NSInteger 定义为long)。 NSIntegerios 定义可能会改变,从而导致相同的崩溃。最好使用您测试过的明确数字。 正如@BenedictCohen 在评论中提到的,这在64 位iOS 设备上不起作用,因为NSInteger 被定义为long。 My solution was to add a fixed amount (essentially: realCount * 201) this way, i have 100 duplicate datasets each side (plus the actual datasource) and then when the picker stops scrolling, i move back to the central datasource. 这个方法也搞砸了 VoiceOver 功能,它会读出“[NSIntegerMax] 的[item]” 在 iOS 9 模拟器上失败,'NSInternalInconsistencyException', reason: 'Failed to allocate data stores for 9223372036854775807 rows in section 0. Consider using fewer rows'【参考方案2】:

我在这里找到了答案:

http://forums.macrumors.com/showthread.php?p=6120638&highlight=UIPickerView#post6120638

当它询问一行的标题时,给它: 代码:

return [rows objectAtIndex:(row % [rows count])];

当它说用户 didSelectRow:inComponent: 时,使用如下内容:

代码:

//we want the selection to always be in the SECOND set (so that it looks like it has stuff before and after)
if (row < [rows count] || row >= (2 * [rows count]) ) 
    row = row % [rows count];
    row += [rows count];
    [pickerView selectRow:row inComponent:component animated:NO];

似乎Uipickerview不支持本地周围的包装,但是您可以通过插入更多要显示的数据以及选择器停止,将组件居中到数据集的中间时来欺骗它。

【讨论】:

【参考方案3】:

只需多次创建一个数组,这样您就可以多次获得数字。让我们说什么时候想要从 0 到 23 的数字并将其放入一个数组中。我们会这样做 10 次...

NSString *stdStepper;

    for (int j = 0; j<10; j++) 
        for(int i=0; i<24; i++)
        
            stdStepper = [NSString stringWithFormat:@"%d", i];

            [_hoursArray addObject:stdStepper];

        
    

稍后我们将第 0 行设置为这样选择

[_hoursPickerView selectRow:120 inComponent:0 animated:NO];

【讨论】:

以上是关于你如何让 UIPickerView 组件环绕?的主要内容,如果未能解决你的问题,请参考以下文章

相互切换2个UIPickerview的组件

如何使用数据快速优化代码和加载 UIPickerView?

iOS 7 UIPickerView 非选中行曲率修改多个组件

如何限制 UIPickerView 组件

是否有适用于 iOS 的完全可定制的类似 UIPickerView 的开源组件?

android中如何让文字环绕图片