UIPickerView - 循环数据

Posted

技术标签:

【中文标题】UIPickerView - 循环数据【英文标题】:UIPickerView - Loop the data 【发布时间】:2014-09-26 15:26:00 【问题描述】:

我目前正在使用 Swift 开发一个应用程序,其中我使用 UIPickerView,请参见下面的图片。目前 UIPickerView 在用户滚动到最后一个数据时停止,但我希望它永远不会停止。我希望可以从第一个数据开始,只需在您处于底部时继续滚动即可。或在顶部时向上滚动。我希望它像 Apple 的 Countdown 一样,您可以随时向上或向下拖动。

我想要的样子:

目前的情况:

【问题讨论】:

【参考方案1】:

这里有四个步骤——我们将设置一些常量来保存选择器视图数据和一些配置,然后我们将添加 UIPickerViewDataSourceUIPickerViewDelegate 方法,我们将结束viewDidLoad 初始化。

一、配置:

private let pickerViewData = Array(0...59)     // contents will be 0, 1, 2, 3...59, change to whatever you want
private let pickerViewRows = 10_000            // any big number
private let pickerViewMiddle = ((pickerViewRows / pickerViewData.count) / 2) * pickerViewData.count

注意pickerViewMiddle 常量——计算它可以很容易地从行偏移中获取我们的当前值。关于数据源——我们实际上只需要为每一行提供一个标题,但我们将添加一个帮助方法来将行号转换为数组中的值:

extension ViewController : UIPickerViewDataSource 
    func valueForRow(row: Int) -> Int 
        // the rows repeat every `pickerViewData.count` items
        return pickerViewData[row % pickerViewData.count]
    

    func rowForValue(value: Int) -> Int? 
        if let valueIndex = find(pickerViewData, value) 
            return pickerViewMiddle + value
        
        return nil
    

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! 
        return "\(valueForRow(row))"
    

最后我们将设置委托:

extension ViewController : UIPickerViewDelegate 
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int 
        return 1
    

    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int 
        return pickerViewRows
    

    // whenever the picker view comes to rest, we'll jump back to
    // the row with the current value that is closest to the middle
    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) 
        let newRow = pickerViewMiddle + (row % pickerViewData.count)
        pickerView.selectRow(newRow, inComponent: 0, animated: false)
        println("Resetting row to \(newRow)")
    


要初始化,请在您的 viewDidLoad 中设置委托和数据源,然后移动到选择器中间的正确行:

self.picker.delegate = self
self.picker.dataSource = self
let initialValue = 0
if let row = rowForValue(initialValue) 
    self.picker.selectRow(row, inComponent: 0, animated: false)

// or if you just want to start in the middle:
// self.picker.selectRow(pickerViewMiddle, inComponent: 0, animated: false)

【讨论】:

正如this answer 中提到的,将选取器中的行数设置为“任何大数字”会破坏 VoiceOver,给出“[大数字] 的 [项目]”,这是一个可访问性问题。有什么办法吗? 嗨,内特!你在哪里声明你的配置?我在课堂上声明了它,但是给我一个错误,实例不能在我的课堂上使用。 嗨,Nate,你能在 C# 中将它转换为 Xamarin.ios,因为我遇到了同样的问题。但我不知道目标c。【参考方案2】:

这里已经回答了这个问题:How do you make an UIPickerView component wrap around?

基本思想是,您只需创建一个选择器视图,其中包含足够多的重复行,用户可能永远不会到达末尾。在上面的答案中,存在如何创建行数的问题,因此我编辑了该部分并在下面提供了剩余的答案。这是objective-c,因此您需要将其转换为swift以供您使用...

@implementation ViewController
NSInteger numberItems;
NSInteger currentValue;

- (void)viewDidLoad 
    [super viewDidLoad];
    self.pickerView.delegate = self;
    numberItems = 60;
    currentValue = 0;
    [self.pickerView selectRow:(currentValue + (numberItems * 50)) inComponent:0 animated:NO];
    [self.view addSubview:self.pickerView];


- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];


- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component 
    //return NSIntegerMax; -- this does not work on 64-bit CPUs, pick an arbitrary value that the user will realistically never scroll to like this...
    return numberItems * 100;


- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component 
    return [NSString stringWithFormat:@"%ld", row % numberItems];


- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component 
    NSInteger rowValueSelected = row % numberItems;
    NSLog(@"row value selected: %ld", (long)rowValueSelected);


@end

【讨论】:

以上是关于UIPickerView - 循环数据的主要内容,如果未能解决你的问题,请参考以下文章

原型 tableviewcell 内的 UIPickerView 没有选择指示器

UIPickerView - 循环数据

ios UIPickerView 技巧集锦(包括循环滚动)

如何与 Xamarin UITest 中的自定义键盘进行交互?

iOS 为啥我的 UIPickerview 方法在循环?

json for 循环并将其放置在 UIPickerView