问题
I have to change the color of the selected row in a UIPickerView
.
I did managed to change the color, i know that the question already have several replies, anyway those do not satisfy me: with those implementation, the animation of the pickerview is glitchy and i don't like it.
This is the code of the current solution
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
}
And when the user scrolls, I reload the components.
But as you can see in the images below, when a user scroll, the green field moves and there is a fraction of seconds in which the green label is below the selector indicator and the selected row is black.
What I'd like to have is that everything inside the selector indicator is green while what outside keeps the default shades of grey.
How can I implement this?
回答1:
You should use attributedTitleForRow
for this instead, no need to create your own label with an NSAttributedString
. In your didSelectRow
your reload all your components to be able to reset all colors and set the new selected one to green.
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()
}
回答2:
You can simply use this code
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:
Better effects with performance a little bad.
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
}
}
来源:https://stackoverflow.com/questions/47048600/change-color-of-selectedrow-in-uipickerview-also-when-rolling