[英]swift collectionview cell didSelectItemAtIndexPath shows wrong cell if you scroll
假設您在UICollectionView的單元格(來自圖像名稱數組)中設置了一堆圖像視圖,並在設置項目時默認設置為alpha 0.5。
然后在didSelectItemAtIndexPath函數中將圖像視圖的alpha設置為1.0,因此當用戶點擊時它變為alpha 1。
這在用戶點擊單元格時有效,但如果用戶滾動則不會保留,因為該單元正在某些其他級別上被UI重用。
結果是另一個單元格(滾動時)變為alpha 1.0並且您選擇的原始單元格將恢復為之前的alpha 0.5外觀。
我知道這一切都是為了在設備上提高效率,但我仍然沒有弄清楚如何讓它在所選項目持續存在的情況下正常工作。
回答
Apple 確實為可用於更改背景顏色,陰影效果或輪廓等的單元格提供selectedBackgroundView。它們還允許您使用“默認”和“突出顯示”狀態在單元格內使用圖像。
這兩種方法都會在選擇正確的情況下持續存在。
但是,如果您希望使用屬性或不同的元素之一來指示您選擇的狀態,則必須使用包含對當前所選項的引用的單獨數據模型元素。 然后,當用戶選擇一個項目時,您必須重新加載視圖控制器數據,從而導致所有單元格被重繪,並將所選狀態應用於其中一個單元格。
下面是我用來解決問題的代碼的主旨,感謝Matt的耐心和幫助。
所有這些都可以位於主UICollectionView Controller類文件中,或者數據數組和結構可以位於自己的swift文件中,如果您需要在項目的其他位置使用它。
數據和數據模型:
let imagesArray=["image1", "image2", "image3", ...]
struct Model {
var imageName : String
var selectedState : Bool
init(imageName : String, selectedState : Bool = false){
self.imageName = imageName
self.selectedState = selectedState
}
}
UICollectionView控制器的代碼
// create an instance of the data model for images and their status
var model = [Model]()
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// build out a data model instance based on the images array
for i in 0..<imagesArray.count {
model.append(Model(imageName: imagesArray[i]))
// the initial selectedState for all items is false unless otherwise set
}
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imagesArray.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// when the collectionview is loaded or reloaded...
let cell:myCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! myCollectionViewCell
// populate cells inside the collectionview with images
cell.imageView.image = UIImage(named: model[indexPath.item].imageName)
// set the currently selected cell (if one exists) to show its indicator styling
if(model[indexPath.item].selectedState == true){
cell.imageView.alpha = 1.0
} else {
cell.imageView.alpha = 0.5
}
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
// when a cell is tapped...
// reset all the selectedStates to false in the data model
for i in 0..<imagesArray.count {
model[i].selectedState = false
}
// set the selectedState for the tapped item to true in the data model
model[indexPath.item].selectedState = true
// refresh the collectionView (triggering cellForItemAtIndexPath above)
self.collectionView.reloadData()
}
但是如果用戶滾動它並不會持續存在,因為UI會在其他某個級別上重復使用該單元格
因為你做錯了。 在didSelect
, 不對任何細胞進行任何更改 。 而是,更改基礎數據模型 ,並重新加載集合視圖。 這都是關於你的數據模型和你的cellForItemAtIndexPath:
的實現cellForItemAtIndexPath:
這是單元格和插槽(項目和部分)相遇的地方。
這是一個簡單的例子。 我們只有一個部分,因此我們的模型可以是模型對象的數組。 我將假設100行。 我們的模型對象只包含要進入此項目的圖像名稱,以及是否淡化此圖像視圖的知識:
struct Model {
var imageName : String
var fade : Bool
}
var model = [Model]()
override func viewDidLoad() {
super.viewDidLoad()
for i in 0..<100 {
// ... configure a Model object and append it to the array
}
}
override func collectionView(
collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 100
}
現在,選擇項目時會發生什么? 我會假設單一選擇。 因此,在我們的模型中,該項目和其他項目都不應標記為淡入淡出。 然后我們重新加載數據:
override func collectionView(cv: UICollectionView,
didSelectItemAtIndexPath indexPath: NSIndexPath) {
for i in 0..<100 {model[i].fade = false}
model[indexPath.item].fade = true
cv.reloadData()
}
所有實際工作都在cellForItemAtIndexPath:
完成cellForItemAtIndexPath:
。 這項工作基於模型 :
override func collectionView(cv: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let c = self.collectionView!.dequeueReusableCellWithReuseIdentifier(
"Cell", forIndexPath: indexPath) as! MyCell
let model = self.model[indexPath.item]
c.iv.image = UIImage(named:model.imageName)
c.iv.alpha = model.fade ? 0.5 : 1.0
return c
}
你的邏輯不正確。 didSelectItemAtIndexPath用於在選擇單元格時觸發某些內容。 所有這個功能都應該包含:
let cell:stkCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! stkCollectionViewCell
cell.imageView.alpha = 1.0
selectedIndex = indexPath.item
然后在您的cellForItemAtIndexPath函數中,您應該具有設置單元格的邏輯,因為這是重用單元格的位置。 所以這個邏輯應該在那里:
if (indexPath.item == selectedIndex){
print(selectedIndex)
cell.imageView.alpha = 1.0
}
else {
cell.imageView.alpha = 0.5
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.