【问题标题】:Change color of selectedRow in UIPickerView, also when rolling在 UIPickerView 中更改选定行的颜色,滚动时也是如此
【发布时间】:2017-11-01 05:10:58
【问题描述】:

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

我确实设法改变了颜色,我知道这个问题已经有好几个回复了,无论如何这些都不能让我满意:通过这些实现,pickerview 的动画有问题,我不喜欢它。

这是当前解决方案的代码

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
}

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

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

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

我该如何实现?

【问题讨论】:

    标签: ios swift uikit uipickerview


    【解决方案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()
    }
    

    【讨论】:

    • 已经试过了,但是不行。我仍然可以看到年份变黑然后变绿。
    • 不明白你的意思。滚动时要删除绿色吗?
    • 不,我想要这样,当您向上或向下滚动时,选择视图中有一半字符串,另一个(未选择)中有一半字符串,它变成一半绿色和一半灰色。在默认实现中,没有颜色,当您滚动时,您可以看到标签半纯黑色和半黑色,alpha
    • AttributeTitleForRow 有效。 self.model 引用您的数组,其中数据加载到选择器中。
    • 为什么不只是pickerView.reloadComponent(component)?
    【解决方案2】:

    你可以简单地使用这个代码

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

    【讨论】:

    • 你找到方法了吗?所选行一直持续到用户移开手指
    【解决方案3】:

    效果更好,性能稍差。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多