【发布时间】:2021-12-02 09:07:14
【问题描述】:
我想要一个自定义视图,其中包含一行 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
因此,如果我查看DigitControlItem(实际上是UIPickerView)一切正常,但如果它是集合视图的一部分(NumberView 类),它似乎是不可见的。任何想法这里可能有什么问题?
【问题讨论】:
标签: swift uikit swift-playground