Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
337 views
in Technique[技术] by (71.8m points)

ios - UIPickerView - Loop the data

I'm currently developing an app using Swift where I use a UIPickerView, see below for image. Currently the UIPickerView stops when the user has scrolled to the last data, but i want it no never stop. I want it to be possible to start from the first data by just keep on scrolling when you're at the bottom. Or scroll up when at the top. I want it to be like Apple's Countdown where you can drag up or down whenever you want.

How I want it to be:

enter image description here

How it currently is:

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There will be four steps here -- we'll set up some constants to hold the picker view data and a bit of configuration, then we'll add UIPickerViewDataSource and UIPickerViewDelegate methods, and we'll end with the viewDidLoad initialization.

First, the configuration:

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

Note the pickerViewMiddle constant -- it's calculated to make it very easy to get our current value from the row offset. On to the data source -- we really only need to provide a title for each row, but we'll add a helper method to convert a row number to a value from the array:

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

And finally we'll set up the delegate:

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

}

To initialize, in your viewDidLoad set the delegate and data source and then move to the correct row in the middle of your picker:

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)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...