Skip to content

About customizing row height for RxPickerViewViewAdapter. #423

Open
@HowsonLiu

Description

@HowsonLiu
lazy var pickerAdapter: RxPickerViewViewAdapter<Array<Any>> = {
        return RxPickerViewViewAdapter<Array<Any>>(components: [],
                                                   numberOfComponents: { _,_,_ in 1 },
                                                   numberOfRowsInComponent: { _,_,items,_ in items.count},
                                                   viewForRow: { [weak self] _,_,items,row,_,_ -> UIView in
            let label = Label(text: "\(items[row])")
            label.font = self?.pickerFont
            if self?.pickerAxis == .horizontal {
                label.transform = CGAffineTransform(rotationAngle: .pi / 2)
            }
            return label
        })
    }()

Observable.just(pickerItems)
                .bind(to: pickerView.rx.items(adapter: pickerAdapter))
                .disposed(by: pickerDisposeBag)

I would like to set the height of the label to 100. I see that RxPickerViewViewAdapter inherits from UIPickerViewDelegate.However, there is no handling of rowHeightForComponent in RxPickerViewViewAdapter. I tried adding an extension to RxPickerViewViewAdapter

extension RxPickerViewViewAdapter {
   public func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
        return 100
    }
}

or subclassing it and overriding the rowHeightForComponent method.

open class RxPickerViewHeightViewAdapter<Components>: RxPickerViewViewAdapter<Components> {
    
    public typealias HeightOfRowsInComponent = (
        _ dataSource: RxPickerViewHeightViewAdapter<Components>,
        _ pickerView: UIPickerView,
        _ components: Components,
        _ component: Int
    ) -> CGFloat
    
    private let heightOfRowsInComponent: HeightOfRowsInComponent
    
    fileprivate var components: Components
    
    public init(components: Components,
                numberOfComponents: @escaping NumberOfComponents,
                numberOfRowsInComponent: @escaping NumberOfRowsInComponent,
                viewForRow: @escaping ViewForRow,
                heightOfRowsInComponent: @escaping HeightOfRowsInComponent) {
        self.components = components
        self.heightOfRowsInComponent = heightOfRowsInComponent
        super.init(components: components,
                   numberOfComponents: numberOfComponents,
                   numberOfRowsInComponent: numberOfRowsInComponent,
                   viewForRow: viewForRow)
    }
    
    open func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
        return self.heightOfRowsInComponent(self, pickerView, components, component)
    }   
}

but they both didn't work
In the end, I modified the source code of RxPickerViewViewAdapter

open class RxPickerViewViewAdapter<Components>: RxPickerViewDataSource<Components>, UIPickerViewDelegate {
    /**
     - parameter dataSource
     - parameter pickerView
     - parameter components
     - parameter row
     - parameter component
     - parameter view
    */
    public typealias ViewForRow = (
        _ dataSource: RxPickerViewViewAdapter<Components>,
        _ pickerView: UIPickerView,
        _ components: Components,
        _ row: Int,
        _ component: Int,
        _ view: UIView?
    ) -> UIView
    
    private let viewForRow: ViewForRow
    
    /**
     - parameter dataSource
     - parameter pickerView
     - parameter components
     - parameter component
    */
    public typealias RowHeightForComponent = (
        _ dataSource: RxPickerViewViewAdapter<Components>,
        _ pickerView: UIPickerView,
        _ components: Components,
        _ component: Int
    ) -> CGFloat
    
    private let rowHeightForComponent: RowHeightForComponent

    /**
     - parameter components: Initial content value.
     - parameter numberOfComponents: Implementation of corresponding delegate method.
     - parameter numberOfRowsInComponent: Implementation of corresponding delegate method.
     - parameter viewForRow: Implementation of corresponding adapter method that converts component to `UIView`.
     */
    public init(components: Components,
                numberOfComponents: @escaping NumberOfComponents,
                numberOfRowsInComponent: @escaping NumberOfRowsInComponent,
                rowHeightForComponent: @escaping RowHeightForComponent,
                viewForRow: @escaping ViewForRow) {
        self.viewForRow = viewForRow
        self.rowHeightForComponent = rowHeightForComponent
        super.init(components: components,
                   numberOfComponents: numberOfComponents,
                   numberOfRowsInComponent: numberOfRowsInComponent)
    }
    
    open func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
        return viewForRow(self, pickerView, components, row, component, view)
    }
    
    open func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
        return rowHeightForComponent(self, pickerView, components, component)
    }
}

and it worked
so are there any better solutions about this question? should i submit a mr?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions