在UIPickerView中更改selectedRow的颜色,也在滚动时更改

时间:2017-11-01 05:10:59

标签: ios swift uikit uipickerview

我必须更改UIPickerView中所选行的颜色。

我确实设法改变了颜色,我知道这个问题已经有了几个回复,无论如何那些不满足我:对于那些实现,挑选视图的动画是毛病,我不喜欢它。 / p>

这是当前解决方案的代码

func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {

    var label: UILabel
    if view == nil {
      label = UILabel()
    } else if view is UILabel {
      label = view as! UILabel
    } else {
      label = UILabel()
    }

    let title: NSAttributedString
    if self.model?.selectedValue == row {
      title = UIPickerView.attributedString(with: .selectedRow, text: "\(model?.years[row] ?? 0)")
    } else {
      title = UIPickerView.attributedString(with: .unselectedRow, text: "\(model?.years[row] ?? 0)")
    }

    label.attributedText = title
    return label
}

当用户滚动时,我会重新加载组件。

但是正如您在下面的图片中所看到的,当用户滚动时,绿色区域会移动,绿色标签位于选择器指示器下方并且所选行为黑色的时间段为几分之一。

pickerview while scrolling after scroll but before the reload

我想要的是选择器指示器内的所有内容都是绿色,而外部保持默认的灰色阴影。

我该如何实现?

3 个答案:

答案 0 :(得分:1)

您应该使用attributedTitleForRow代替,而不需要使用NSAttributedString创建自己的标签。在didSelectRow中重新加载所有组件,以便能够重置所有颜色,并将新选择的颜色设置为绿色。

func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
    let color = (row == pickerView.selectedRow(inComponent: component)) ? UIColor.green : UIColor.black
    return NSAttributedString(string: self.model[row], attributes: [NSForegroundColorAttributeName: color])
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    pickerView.reloadAllComponents()
}

答案 1 :(得分:0)

您可以简单地使用此代码

func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
    let label = view as? UILabel ?? UILabel()

    if pickerView.selectedRow(inComponent: component) == row {
        label.backgroundColor = UIColor.green
        label.frame = CGRect(x: 0, y: 0, width: 36, height: 36)
        label.layer.cornerRadius = 18
        label.layer.masksToBounds = true
        label.textColor = .white
        label.text = String(numbers[row])
        label.textAlignment = .center
    }else {
        label.layer.cornerRadius = 25
        label.frame = CGRect(x: 0, y: 0, width: 36, height: 36)
        label.layer.cornerRadius = 18
        label.layer.masksToBounds = true
        label.textColor = .white
        label.text = String(numbers[row])
        label.textAlignment = .center
    }
    return label
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    pickerView.reloadAllComponents()
}

答案 2 :(得分:0)

效果更好,但性能稍差。

extension ViewController: UIPickerViewDelegate{

    func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
        let info = BeatScalar.generalRates[row]
        let general = GeneralRateItem(info.cn, info.ita, info.val)
        // gray every row
        general.unselected()
        decorateView(pickerView, row: row)
        return general
    }


    // Here is the logic 
    func decorateView(_ picker: UIPickerView, row: Int){

        var frame = picker.frame
        frame.origin.y = frame.origin.y + frame.size.height * 0.42
        frame.size.height = frame.size.height * 0.16

        let mini = max(row-1, 0)
        //   19 is total number
        let maxi = min(18, row+1)
        for i in mini...maxi{
            if i != row, let item = picker.view(forRow: i, forComponent: 0) as? GeneralRateItem{
                let f = item.convert(item.frame, to: picker)
                if frame.intersects(f) == false{
                    // highlight the center row
                    item.selected()
                }
            }
        }
    }

    func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
        return 44
    }
}


extension ViewController: UIPickerViewDataSource{
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {       // 19 is total number
        return 19
    }
}