Search code examples
swiftuipickerview

PickerView with decimal point


I used a UIPickerView with four components to enter digits without a keyboard. I added a decimal point, with just a '.' in a UILabelView. See the screen to get the idea.

UIPickerView

My code is for the UIPickerView is:

func numberOfComponents(in weightPickerView: UIPickerView) -> Int {
    return 4
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return loopingMargin * numbers.count
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
  return numbers[row % numbers.count]
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    let currentIndex = row % numbers.count
    digits[component] = currentIndex
    let weightString = "\(digits[0])\(digits[1]).\(digits[2])\(digits[3])"
    weightField.text = weightString
}

And inside viewDidLoad() part of the code is:

override func viewDidLoad() {
    super.viewDidLoad()        
    // Do any additional setup after loading the view.

    weightPickerView.dataSource = self
    weightPickerView.delegate = self
    weightPickerView.selectRow((loopingMargin / 2) * numbers.count, inComponent: 0, animated: false)
    weightPickerView.selectRow((loopingMargin / 2) * numbers.count, inComponent: 1, animated: false)
    weightPickerView.selectRow((loopingMargin / 2) * numbers.count, inComponent: 2, animated: false)
    weightPickerView.selectRow((loopingMargin / 2) * numbers.count, inComponent: 3, animated: false)

}

My question... I would like to add a fifth component with only a '.' in it (so the space gets evenly distributed). How can I do that?


Solution

  • You just need to update your picker view methods to provide the extra component. Assuming you want it in the middle, your code needs to be:

    func numberOfComponents(in weightPickerView: UIPickerView) -> Int {
        return 5
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return component == 2 ? 1 : loopingMargin * numbers.count
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
      return component == 2 ? "." : numbers[row % numbers.count]
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if component != 2 {
            var index = component
            if component > 2 {
                index -= 1
            }
            let currentIndex = row % numbers.count
            digits[index] = currentIndex
            let weightString = "\(digits[0])\(digits[1]).\(digits[2])\(digits[3])"
            weightField.text = weightString
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()        
    
        weightPickerView.dataSource = self
        weightPickerView.delegate = self
        weightPickerView.selectRow((loopingMargin / 2) * numbers.count, inComponent: 0, animated: false)
        weightPickerView.selectRow((loopingMargin / 2) * numbers.count, inComponent: 1, animated: false)
        weightPickerView.selectRow((loopingMargin / 2) * numbers.count, inComponent: 3, animated: false)
        weightPickerView.selectRow((loopingMargin / 2) * numbers.count, inComponent: 4, animated: false)
    }
    

    Assuming the . represents a decimal separator, keep in mind that many users around the world don't use . for a decimal separator. So you really should show the appropriate character. You can get the decimalSeparator property of a NumberFormatter.