2015-10-29 49 views
2

假设您在UICollectionView的单元格(来自图像名称数组)中设​​置一堆图像视图,并在设置项目时默认设置为alpha 0.5。swift collectionview cell didSelectItemAtIndexPath如果滚动显示错误的单元格

然后,您在didSelectItemAtIndexPath func中将图像视图的alpha设置为1.0,所以当用户点击时它变为alpha 1。

这适用于用户点击单元格,但如果用户滚动,则该单元格不会保留,因为该单元格正被其他某个级别的UI重新使用。

结果是更远的另一个单元格(当滚动时)变为alpha 1.0,并且您选择的原始单元格恢复为以前的alpha 0.5外观。

我明白这一切都是为了让设备上的东西更加高效,但我还没有想出如何在选定项目持续存在的情况下正常工作。

ANSWER

苹果对于您可以用它来改变背景颜色,阴影效果,或轮廓等,他们还允许您使用与细胞内的细胞图像提供selectedBackgroundView “默认”和“突出显示”状态。

这两种方法都会在选择正确的情况下持续存在。但是,如果您希望使用属性或不同于指定所选状态的属性或元素之一的元素,则必须使用包含对当前选定项目的引用的单独数据模型元素。然后,当用户选择一个项目时,您必须重新加载视图控制器数据,从而导致单元格全部重新绘制,并将选定状态应用于其中一个单元格。

下面是我用来解决我的问题的代码,谢谢马特的耐心和帮助。

所有这些都可以位于主UICollectionView控制器类文件中,或者如果需要在项目的其他地方使用它,数据数组和结构可以位于其自己的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() 

} 

回答

2

但如果用户滚动,这是因为细胞被重新使用由它不坚持一些其他级别的用户界面

因为你做错了。在didSelect中,使不会更改为任何单元格。相反,请更改底层的数据模型重新加载集合视图。这完全是关于你的数据模型和你的实现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:完成。而这项工作是在模型上基于

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 
} 
+0

Swift与它无关。语法与它无关。这只是一个认识到单元重用的问题,所以唯一稳定的就是数据模型。好的,我已经为你写出了一个完整的实例。 – matt

+0

现在尝试一下,我会在我拥有它时报告。谢谢。 – dmcknight

+0

如果您需要我通过电子邮件发送演示项目,请告诉我。 – matt

0

您的逻辑是不正确。 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 
} 
+0

嘿拉夫沃,我试了一下,但没有奏效。这与我之前尝试的非常相似。如果我可以找到在更新selectedIndex后在didSelect中立即触发“重用”(或重新加载)操作的正确方法,它可能会起作用。 – dmcknight

+0

不是最有效的方法,但我想现实中你可以在didSelect函数中做一个tableView.reloadData()。我觉得其他的东西只是遗漏或被遗漏在某处......或者可能是比较条件,因此它应该起作用。 – Lavvo

+0

当我尝试了第一种建议的方式后,行为与我原来的问题保持一致,这是由于在didSelect函数中设置了imageView.alpha = 1.0所导致的。如果我把这条线取出来,它只会设置阿尔法,如果你选择一些,然后滚动。 – dmcknight

相关问题