UIPickerView - 循环数据

Tho*_*lli 14 uipickerview ios swift ios8

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

我希望如何:

在此输入图像描述

目前的情况如何:

在此输入图像描述

Nat*_*ook 10

这里将有四个步骤 - 我们将设置一些常量来保存选择器视图数据和一些配置,然后我们将添加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
Run Code Online (Sandbox Code Playgroud)

注意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))"
    }
}
Run Code Online (Sandbox Code Playgroud)

最后我们将设置代表:

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)")
    }

}
Run Code Online (Sandbox Code Playgroud)

要初始化,请在您的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)
Run Code Online (Sandbox Code Playgroud)


Bre*_*ato 5

这已经在这里得到了回答: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
Run Code Online (Sandbox Code Playgroud)