我知道这个问题已被多次询问过。
我将UICollectionView
与自定义单元格一起使用,这些单元格具有一些属性,最重要的是UISwitch
的数组以及UILabel
&的数组#39; S。你可以猜到,当我滚动时,标签重叠,开关改变状态。我已经实现了UICollectionViewCell
prepareForReuse
的方法,我在其中清空这些数组并重置主标签文本。
我尝试将不同答案的解决方案结合起来,并且我已经达到了保留标签的程度,但单元格中的开关状态并非如此。我的下一步是创建一个数组以在删除开关之前保留状态,然后将新创建的开关的on属性设置为索引处的此数组的值。这是有效的,直到我非常快速地滚动并切换之前未选择的单元格被选中(或未选中)。这对我来说是一个巨大的问题。
这是我的collectionView cellForItemAtIndexPath
方法:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("pitanjeCell", forIndexPath: indexPath) as! PitanjeCell
// remove views previously created and create array to preserve the state of switches
var selectedSwitches: [Bool] = []
for item: UIView in cell.contentView.subviews {
if (item.isKindOfClass(UILabel) && !item.isEqual(cell.tekstPitanjaLabel)){
item.removeFromSuperview()
}
if (item.isKindOfClass(UISwitch)){
selectedSwitches.append((item as! UISwitch).on)
item.removeFromSuperview()
}
}
// get relevant data needed to place cells programmatically
cell.tekstPitanjaLabel.text = _pitanja[indexPath.row].getText()
let numberOfLines: CGFloat = CGFloat(cell.tekstPitanjaLabel.numberOfLines)
cell.setOdgovori(_pitanja[indexPath.row].getOdgovori() as! [Odgovor])
var currIndex: CGFloat = 1
let floatCount: CGFloat = CGFloat(_pitanja.count)
let switchConstant: CGFloat = 0.8
let switchWidth: CGFloat = cell.frame.size.width * 0.18
let heightConstant: CGFloat = (cell.frame.size.height / (floatCount + 2) + (numberOfLines * 4))
let labelWidth: CGFloat = cell.frame.size.width * 0.9
for item in _pitanja[indexPath.row].getOdgovori() {
// create a switch
let odgovorSwitch: UISwitch = UISwitch(frame: CGRectMake((self.view.frame.size.width - (switchWidth * 2)), currIndex * heightConstant , switchWidth, 10))
odgovorSwitch.transform = CGAffineTransformMakeScale(switchConstant, switchConstant)
let switchValue: Bool = selectedSwitches.count > 0 ? selectedSwitches[Int(currIndex) - 1] : false
odgovorSwitch.setOn(switchValue, animated: false)
// cast current item to relevant class
let obj: Odgovor = item as! Odgovor
// create a label
let odgovorLabel: UILabel = UILabel(frame: CGRectMake((self.view.frame.size.width / 12), currIndex * heightConstant , labelWidth, 20))
odgovorLabel.text = obj.getText();
odgovorLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
odgovorLabel.font = UIFont(name: (odgovorLabel.font?.fontName)!, size: 15)
// add to cell
cell.addSwitch(odgovorSwitch)
cell.addLabel(odgovorLabel)
currIndex++
}
return cell
}
我的自定义单元格还实现了addSwitch
和addLabel
方法,它们将contentView
的元素添加为subview
。
滚动时有什么办法可以保持开关的状态吗?
编辑:根据@Victor Sigler的建议,我创建了一个像这样的二维数组:
var _switchStates: [[Bool]]!
我像这样初始化它:
let odgovori: Int = _pitanja[0].getOdgovori().count
_switchStates = [[Bool]](count: _pitanja.count, repeatedValue: [Bool](count: odgovori, repeatedValue: false))
我改变了我的方法:
for item: UIView in cell.contentView.subviews {
if (item.isKindOfClass(UILabel) && !item.isEqual(cell.tekstPitanjaLabel)){
item.removeFromSuperview()
}
if (item.isKindOfClass(UISwitch)){
_switchStates[indexPath.row][current] = (item as! UISwitch).on
current++
selectedSwitches.append((item as! UISwitch).on)
item.removeFromSuperview()
}
}
最后:
let switchValue: Bool = _switchStates.count > 0 ? _switchStates[indexPath.row][Int(currIndex) - 1] : false
答案 0 :(得分:1)
首先,正如您在UICollectionView
中关于单元格默认行为的问题所说,您需要保存每个单元格的状态,在UISwitch
的情况下,您需要保留本地属性中的状态,而不是cellForRowAtIndexPath
方法,因为每次重复使用单元格时,此方法都会调用。
首先声明一个数组,你要在这个函数之外保存UISwitch
的状态,如下所示:
var selectedSwitches: [Bool] = []
或者您可以声明它,然后在viewDidLoad
实例化它,它取决于您,我建议您在viewDidLoad
中实例化它,并仅将其声明为此类属性:
var selectedSwitches: [Bool]!
然后,您可以根据UISwitch
的状态执行任何操作,当然,保留在更改为on
或off
时保留。
我希望这对你有所帮助。
答案 1 :(得分:0)
我做到了!
最后我实现了这个:
func collectionView(collectionView: UICollectionView, didEndDisplayingCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
var current: Int = 0
var cell = cell as! PitanjeCell
for item: UISwitch in cell.getOdgovoriButtons() {
if(current == _switchStates[0].count) { break;}
_switchStates[indexPath.row][current] = (item).on
current++
}
}
在这个功能中,我保存了状态。
这与prepareForReuse组合:
public override func prepareForReuse() {
self.tekstPitanjaLabel.text = nil
self._odgovoriButtons.removeAll()
self._odgovoriLabels.removeAll()
self._odgovori.removeAll()
super.prepareForReuse()
}
终于做到了!