如何使 UIPickerView.viewForRow 在中心突出显示,重置行变灰?

How to make UIPickerView.viewForRow highlighted in the center , the reset row gray?

如何让它更漂亮?

如下图:中心行突出显示,其余行灰色。

代码如下:

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

github

中的更多代码

我需要使用func pickerView(_ pickerView: UIPickerView, viewForRow,因为

上面的代码工作正常,缺点是它计算量大,并且用一些数学进行了硬编码。

我真的不懂逻辑。我认为逻辑结果恰恰相反。

而 Xcode 总是报告,

[Assert] Attempted to call -cellForRowAtIndexPath: on the table view while it was in the process of updating its visible cells, which is not allowed. Make a symbolic breakpoint at UITableViewAlertForCellForRowAtIndexPathAccessDuringUpdate to catch this in the debugger and see what caused this to occur. Perhaps you are trying to ask the table view for a cell from inside a table view callback about a specific row? Table view: ; layer = ; contentOffset: {0, 19}; contentSize: {314, 836}; adjustedContentInset: {127.66666666666667, 0, 127.33333333333331, 0}; dataSource: ; layer = >>

如何改进代码?


我有别的想法,

访问 pickerView 的子视图来完成它

如何做的更整齐?

这对我有用:

func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
    let label = UILabel()
    label.text = "\(value(forRow: row))"
    label.textColor = UIColor.black
    DispatchQueue.main.async {  // chance color of the middle row
        if let label = pickerView.view(forRow: row, forComponent: component) as? UILabel {
            label.textColor = UIColor.white
        }
    }
    return label
}

它在幕后的实际运作方式:

UIPickerView 包含 3 个不同的 UITableViews。上中下部分(我的case是改造过的,别介意)

函数viewForRow提供者returnsview,但你不知道view是为哪个部分提供的。但是当你通过 pickerView.view(forRow: row, forComponent: component) 请求 view 时,它总是 returns 你在中间,然后你就可以做你的造型了。它在 DispatchQueue.main.async 中的原因是您必须等到 pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView 结束,方法是将其安排到渲染的末尾 queue.