swift - UIKit:UICollectionViewCell 内的 UIPickerView 变得不可见
问题描述
我想要一个带有一行的自定义视图UIPickerView
来显示一个数字。这是我的游乐场:
import PlaygroundSupport
import UIKit
import CoreGraphics
typealias DigitItemSize = (CGFloat, CGFloat)
class NumberViewItemArea {
private var digitWidth_ : CGFloat = 0
private var digitHeight_ : CGFloat = 0
private var numberOfDigits_ : Int = 0
private var area_ : CGRect? = nil
private var spaceBetweenDigits_ : CGFloat = 0
private func recalculateArea()
{
if numberOfDigits_ < 1 {
area_ = nil
} else {
area_ = CGRect(x:0,
y:0,
width : digitWidth_*CGFloat(numberOfDigits_) + spaceBetweenDigits_*CGFloat(numberOfDigits_-1),
height: digitHeight_)
}
}
init(itemWidth : CGFloat,
itemHeight : CGFloat,
numOfDigits : Int,
spaceBetweenDigits : CGFloat) {
digitWidth_ = itemWidth
digitHeight_ = itemHeight
numberOfDigits_ = numOfDigits
spaceBetweenDigits_ = spaceBetweenDigits
recalculateArea()
}
init() {}
public var digitWidth : CGFloat {
get {
return digitWidth_
}
set(newWidth) {
digitWidth_ = newWidth
recalculateArea()
}
}
public var digitHeight : CGFloat {
get {
return digitHeight_
}
set(newHeight) {
digitHeight_ = newHeight
recalculateArea()
}
}
public var numberOfDigits : Int {
get {
return numberOfDigits_
}
set(newValue) {
numberOfDigits_ = newValue
recalculateArea()
}
}
public var spaceBetweenDigits : CGFloat {
get {
return spaceBetweenDigits_
}
set(newValue) {
spaceBetweenDigits_ = newValue
recalculateArea()
}
}
public var area : CGRect? {
get {
return area_
}
}
}
public class DigitControlItem: UIView {
lazy var categoryPickerView: UIPickerView = {
let pv = UIPickerView()
pv.dataSource = self
pv.backgroundColor = .white
pv.delegate = self
pv.translatesAutoresizingMaskIntoConstraints = false
return pv
}()
let dataArray = ["0", "1", "2", "3", "4","5","6","7","8","9"]
public override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
setupSettingPickerView()
}
private func setupSettingPickerView() {
addSubview(categoryPickerView)
let constraints = [
categoryPickerView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 0),
categoryPickerView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: 0),
categoryPickerView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0),
categoryPickerView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0)
]
NSLayoutConstraint.activate(constraints)
}
}
extension DigitControlItem: UIPickerViewDataSource, UIPickerViewDelegate {
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return dataArray.count
}
public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
let row = dataArray[row]
return row
}
}
class DigitItem: UICollectionViewCell {
private let digitArea : DigitControlItem = {
let view = DigitControlItem(frame : .zero)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
contentView.addSubview(digitArea)
let constraints = [
digitArea.topAnchor.constraint(equalTo: contentView.topAnchor),
digitArea.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
digitArea.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
digitArea.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
]
NSLayoutConstraint.activate(constraints)
}
}
class NumberView : UIView {
private var digitItemSize : DigitItemSize = (0, 0)
private var numberOfDigitItems : Int = 0
private var spaceBetweenItems : CGFloat = 0
private lazy var digitsCollection : UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
view.register(DigitItem.self,
forCellWithReuseIdentifier: String(describing: DigitItem.self))
view.dataSource = self
view.delegate = self
view.backgroundColor = .white
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
public override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
convenience init(areaProvider : NumberViewItemArea) {
guard let rect = areaProvider.area else {
self.init(frame : .zero)
return
}
self.init(frame: rect)
numberOfDigitItems = areaProvider.numberOfDigits
spaceBetweenItems = areaProvider.spaceBetweenDigits
digitItemSize = (areaProvider.digitWidth, areaProvider.digitHeight)
digitsCollection.reloadData()
}
private func setupView()
{
addSubview(digitsCollection)
let constraints = [
digitsCollection.topAnchor.constraint(equalTo: topAnchor, constant: 0),
digitsCollection.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0),
digitsCollection.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0),
digitsCollection.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0)
]
NSLayoutConstraint.activate(constraints)
}
}
extension NumberView : UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numberOfDigitItems
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell =
digitsCollection.dequeueReusableCell(withReuseIdentifier:
String(describing: DigitItem.self),
for: indexPath) as! DigitItem
// cell.imageName = PhotoGalleryData.images[indexPath.row]
return cell
}
}
extension NumberView : UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: digitItemSize.0, height: digitItemSize.1)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return spaceBetweenItems
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
let itemArea = NumberViewItemArea(itemWidth: 32,
itemHeight:32,
numOfDigits:1,
spaceBetweenDigits:2)
//let item = DigitControlItem(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
let item = NumberView(areaProvider: itemArea)
PlaygroundPage.current.liveView = item
因此,如果我查看 a DigitControlItem
(UIPickerView
实际上是 a )一切正常,但如果它是集合视图(NumberView
类)的一部分,它似乎是不可见的。任何想法这里可能有什么问题?
解决方案
问题来自选择器视图的默认委托。我解决了定义自己的标签的问题:
public func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
var label = UILabel()
if let v = view as? UILabel { label = v }
label.text = dataArray[row]
label.textColor = UIColor.white
label.textAlignment = .center
return label
}
推荐阅读
- binding - 在同一 IIS 站点上根据端口号更改行为
- docker - 不同数据中心之间的 Docker 覆盖网络
- r - 将数据集与R中的csv文件中的数据匹配
- java - Spring MVC 中用于自定义 405 错误响应的可用选项?
- sql - 处理“英寸”标记的 SQL 字符串
- python - Python django admin:如何在管理页面中仅显示属于特定模型的项目?
- javascript - 固定页眉和固定侧导航与静态页脚,侧导航与页脚折叠
- javascript - JavaScript:在包含的表格中设置背景颜色
- reactjs - 如何验证 ReactJS 中的数字输入
- python - QTableview Select Item from filtered model