2014-09-26 178 views
10

我目前正在開發一個使用Swift的應用程序,我使用UIPickerView,請參閱下面的圖像。目前,當用戶滾動到最後一個數據時,UIPickerView停止,但我希望它永不停止。我希望可以從第一個數據開始,只需在底部滾動即可。或者在頂部向上滾動。我希望它能像蘋果的倒計時一樣,你可以隨時上下拖動。UIPickerView - 循環數據

如何我希望它是:

enter image description here

如何目前,它是:

enter image description here

回答

9

會有這裏的四個步驟 - 我們將設置一些常量保持選擇器視圖的數據和那麼我們將添加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))" 
    } 
} 

最後,我們」 LL設置委託:

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) 
+0

謝謝!它完美的工作! – ThomasGulli 2014-09-26 20:07:20

+1

正如[本答案](http://stackoverflow.com/a/367436/172218)中提到的那樣,將選取器中的行數設置爲「任何大數字」將VoiceOver擰緊,給出[[大] ]「,這是一個可訪問性問題。任何方式在這個? – 2015-07-08 09:30:45

+0

嗨,內特!你在哪裏聲明你的配置?我在我的課堂上宣佈它,但給我一個錯誤,實例不能在我的課堂上使用。 – 2016-08-01 04:20:37

2

這一點已經在這裏找到答案:How do you make an UIPickerView component wrap around?

其基本思想是,您只需創建一個具有足夠大量重複行的選擇器視圖,用戶可能永遠不會到達最後。在上面的答案中,如何創建行數有一個問題,因此我編輯了該部分並在下面提供了其餘的答案。這是Objective-C的,所以你需要將其轉換爲迅速達到你的目的......

@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