Ios UICollectionView单元格在重新加载数据时调整大小不正确()
“我的视图”有一个表视图,每行上都有一个集合视图。集合单元格有一个文本字段(以及其中的一个子类)、一个标签和一个文本视图,这些字段都是全尺寸的,并且根据单元格位置,除了一个之外,其余都是隐藏的 编辑其中一个文本字段时,委托(CollectionView)会将新值传递回视图控制器以更改数组,然后在其中包含计算数据时重新加载相应的单元格 问题是第二次编辑其中一个文本字段时,两个单元格交换宽度,如果再编辑两次文本字段,似乎会交换回来,但边框保持在错误的位置 初始加载后的表格: 两次更改数量后的表格 文本字段和视图代理方法Ios UICollectionView单元格在重新加载数据时调整大小不正确(),ios,swift,Ios,Swift,“我的视图”有一个表视图,每行上都有一个集合视图。集合单元格有一个文本字段(以及其中的一个子类)、一个标签和一个文本视图,这些字段都是全尺寸的,并且根据单元格位置,除了一个之外,其余都是隐藏的 编辑其中一个文本字段时,委托(CollectionView)会将新值传递回视图控制器以更改数组,然后在其中包含计算数据时重新加载相应的单元格 问题是第二次编辑其中一个文本字段时,两个单元格交换宽度,如果再编辑两次文本字段,似乎会交换回来,但边框保持在错误的位置 初始加载后的表格: 两次更改数量后的表格
func textFieldDidEndEditing(_ textField: UITextField) {
let currencyField = textField as! CurrencyField
let indexPath = indexPathForCellWithSubview(cellSubview: textField)!
(dataSource as! DetailViewController).changeData(tableRow: tag, collectionItem: indexPath.row, newData: currencyField.decimal)
let indexPaths: [IndexPath] = [IndexPath(row: 1, section: 0),IndexPath(row: 2, section: 0),IndexPath(row: 4, section: 0),IndexPath(row: 5, section: 0)]
collectionViewLayout.invalidateLayout()
reloadItems(at: indexPaths)
}
func textViewDidEndEditing(_ textView: UITextView) {
let indexPath = indexPathForCellWithSubview(cellSubview: textView)!
let indexPaths: [IndexPath] = [IndexPath(row: 1, section: 0),IndexPath(row: 2, section: 0),IndexPath(row: 4, section: 0),IndexPath(row: 5, section: 0)]
let dec = textView.text!.decimalFromString()
if(dec != 0){
(dataSource as! DetailViewController).changeData(tableRow: tag, collectionItem: indexPath.row, newData: dec)
reloadItems(at: indexPaths)
} else {
(dataSource as! DetailViewController).changeData(tableRow: tag, collectionItem: indexPath.row, newData: textView.text!)
}
collectionViewLayout.invalidateLayout()
}
let table4Cells: [Int] = [310,65,100,105]
let table6Cells: [Int] = [250,40,80,50,80,80]
阵列
var dummyData: [[Any]] = [
["Fencing garden",Decimal(1),Decimal(8500.00)],
["Ditching",Decimal(1),Decimal(1950.00)],
["Fred",Decimal(1),Decimal(1950.00)]]
单元格宽度
func textFieldDidEndEditing(_ textField: UITextField) {
let currencyField = textField as! CurrencyField
let indexPath = indexPathForCellWithSubview(cellSubview: textField)!
(dataSource as! DetailViewController).changeData(tableRow: tag, collectionItem: indexPath.row, newData: currencyField.decimal)
let indexPaths: [IndexPath] = [IndexPath(row: 1, section: 0),IndexPath(row: 2, section: 0),IndexPath(row: 4, section: 0),IndexPath(row: 5, section: 0)]
collectionViewLayout.invalidateLayout()
reloadItems(at: indexPaths)
}
func textViewDidEndEditing(_ textView: UITextView) {
let indexPath = indexPathForCellWithSubview(cellSubview: textView)!
let indexPaths: [IndexPath] = [IndexPath(row: 1, section: 0),IndexPath(row: 2, section: 0),IndexPath(row: 4, section: 0),IndexPath(row: 5, section: 0)]
let dec = textView.text!.decimalFromString()
if(dec != 0){
(dataSource as! DetailViewController).changeData(tableRow: tag, collectionItem: indexPath.row, newData: dec)
reloadItems(at: indexPaths)
} else {
(dataSource as! DetailViewController).changeData(tableRow: tag, collectionItem: indexPath.row, newData: textView.text!)
}
collectionViewLayout.invalidateLayout()
}
let table4Cells: [Int] = [310,65,100,105]
let table6Cells: [Int] = [250,40,80,50,80,80]
数据设置和获取
func changeData(tableRow: Int, collectionItem: Int, newData: Any){
var qty: Decimal = dummyData[tableRow][1] as! Decimal
var cost: Decimal = dummyData[tableRow][2] as! Decimal
var total: Decimal
switch(collectionItem){
case 1:
qty = newData as! Decimal
case 2:
cost = newData as! Decimal
case 3:
total = newData as! Decimal
cost = total / qty
case 5:
total = newData as! Decimal
cost = (total / qty) / (1 + vatPC)
default: dummyData[tableRow][collectionItem] = newData
}
dummyData[tableRow][1] = qty
dummyData[tableRow][2] = cost
}
func collectionViewCellText(tag: Int, row: Int) -> String {
var text: String = ""
if(tag == 666){
if(!vatRegistered && row == 3){
return tableHeaderText[5]
} else {
return tableHeaderText[row]
}
} else {
let qty: Decimal = dummyData[tag][1] as! Decimal
let cost: Decimal = dummyData[tag][2] as! Decimal
switch(row){
case 3:
if(vatRegistered){
text = String(describing: vatPC * 100)
} else {
text = String(describing: qty * cost)
}
case 4:
text = String(describing: cost * vatPC)
case 5:
text = String(describing: qty * (cost * (1 + vatPC)))
default:
text = String(describing: dummyData[tag][row])
}
}
return text
}
索引XPath处单元格的大小
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
if(vatRegistered){
return CGSize(width: self.table6Cells[indexPath.row], height:self.collectionCellHeight)
}
return CGSize(width: self.table4Cells[indexPath.row], height:self.collectionCellHeight)
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell",
for: indexPath as IndexPath) as! InvoiceCollectionViewCell
cell.textView.delegate = self
if(collectionView is RJCollectionView){
cell.currencyField.delegate = collectionView as! RJCollectionView
cell.textView.delegate = collectionView as! RJCollectionView
}
if(collectionView.tag == 666){
if(indexPath.row == 0){
cell.addBorder(side: .left, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .right, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .top, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .bottom, thickness: 0.5, color: UIColor.black)
} else {
cell.label.textAlignment = NSTextAlignment.center
cell.textView.textAlignment = NSTextAlignment.center
cell.addBorder(side: .right, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .top, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .bottom, thickness: 0.5, color: UIColor.black)
}
} else {
if(indexPath.row == 0){
cell.addBorder(side: .left, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .right, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .bottom, thickness: 0.5, color: UIColor.black)
} else {
cell.label.textAlignment = NSTextAlignment.center
cell.textView.textAlignment = NSTextAlignment.center
cell.addBorder(side: .right, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .bottom, thickness: 0.5, color: UIColor.black)
}
if(vatRegistered){
switch(indexPath.row){
case 2,5: cell.textType(i: "CurrencyView")
case 3:
cell.textType(i: "TextView")
cell.textView.isUserInteractionEnabled = false
case 4:
cell.currencyField.isUserInteractionEnabled = false
cell.textType(i: "CurrencyView")
default: cell.textType(i: "TextView")
}
} else {
switch(indexPath.row){
case 2,3: cell.textType(i: "CurrencyView")
default: cell.textType(i: "TextView")
}
}
}
if(collectionView.tag == 0){
print(cell.currencyField.bounds.width)
}
cell.text = collectionViewCellText(tag: collectionView.tag, row: indexPath.row)
return cell
}
索引路径行的单元格
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
if(vatRegistered){
return CGSize(width: self.table6Cells[indexPath.row], height:self.collectionCellHeight)
}
return CGSize(width: self.table4Cells[indexPath.row], height:self.collectionCellHeight)
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell",
for: indexPath as IndexPath) as! InvoiceCollectionViewCell
cell.textView.delegate = self
if(collectionView is RJCollectionView){
cell.currencyField.delegate = collectionView as! RJCollectionView
cell.textView.delegate = collectionView as! RJCollectionView
}
if(collectionView.tag == 666){
if(indexPath.row == 0){
cell.addBorder(side: .left, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .right, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .top, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .bottom, thickness: 0.5, color: UIColor.black)
} else {
cell.label.textAlignment = NSTextAlignment.center
cell.textView.textAlignment = NSTextAlignment.center
cell.addBorder(side: .right, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .top, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .bottom, thickness: 0.5, color: UIColor.black)
}
} else {
if(indexPath.row == 0){
cell.addBorder(side: .left, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .right, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .bottom, thickness: 0.5, color: UIColor.black)
} else {
cell.label.textAlignment = NSTextAlignment.center
cell.textView.textAlignment = NSTextAlignment.center
cell.addBorder(side: .right, thickness: 0.5, color: UIColor.black)
cell.addBorder(side: .bottom, thickness: 0.5, color: UIColor.black)
}
if(vatRegistered){
switch(indexPath.row){
case 2,5: cell.textType(i: "CurrencyView")
case 3:
cell.textType(i: "TextView")
cell.textView.isUserInteractionEnabled = false
case 4:
cell.currencyField.isUserInteractionEnabled = false
cell.textType(i: "CurrencyView")
default: cell.textType(i: "TextView")
}
} else {
switch(indexPath.row){
case 2,3: cell.textType(i: "CurrencyView")
default: cell.textType(i: "TextView")
}
}
}
if(collectionView.tag == 0){
print(cell.currencyField.bounds.width)
}
cell.text = collectionViewCellText(tag: collectionView.tag, row: indexPath.row)
return cell
}
注意:collectionview.tag是集合视图所在表上的行。666是标题行。vatRegistered是一个布尔值,当为true时,它将集合视图的宽度设置为6而不是4个单元格更新:
我将整个项目剥离到一个二级项目中,并将collectionview直接放到主视图中,但仍然存在问题
问题似乎是由contentView没有调整单元格大小引起的,这似乎是iOS的一个错误,因此当单元格在重新加载时被推送到堆栈上时,他们切换了顺序,但无论出于何种原因,设置单元格大小都没有重设contentView的大小
添加:
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
对于sizeforitem流布局方法,修复了奇怪的偏移
错误位置的边框取决于我用来添加边框的uiview扩展,它只是将一个设定宽度的视图添加到它要求添加的任何一条边上,在重用单元格时必须删除此边框通常当我尝试做这么复杂的事情时,我会四处看看是否有人做得比我更好;)。也许我修好了程序错误。我想知道这是否是一个恰当的使用集合视图。谢谢布兰登的提示,我将在下一个项目之前查看它,因为我用我的方法修复了bug,在iOSUCUnCIENCEL内容视图的大小上似乎有一个bug,这是一个多么惊人的bug!它仍然存在,2019年末:/从情节提要中选择CollectionView-大小检查器-默认情况下“估计大小”是自动的。更改为“否”已解决我的问题。2020年7月仍然是一个bug-感谢您分享您的问题和经验教训!对我来说,由于我的集合视图单元格高度是固定的,我通过IB解决了这个问题,并将集合视图“单元格大小”和“估计大小”>“自定义”更改为正确的高度。