[英]how to prevent cell reuse of uicollectionview
我使用UICollectionView並引用此鏈接實現scroll table view Fixed single column and row
,如下圖所示。
但是當我想添加shadow
屬性時,它顯示為混亂。
我認為原因是我在渲染可視視圖時重用了cell
,但是我不知道如何解決它:(
在下面提供我的代碼,謝謝您的寶貴時間!
import Foundation
import SwiftyJSON
@objc(RNCollection)
class RNCollection : UICollectionView, UICollectionViewDataSource, UICollectionViewDelegate {
var contentCellIdentifier = "CellIdentifier"
var collectionView: UICollectionView!
static var dataSource = []
static var sections = 0
static var rows = 0
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: CGRectZero, collectionViewLayout: RNCollectionLayout())
self.registerClass(RNCollectionCell.self, forCellWithReuseIdentifier: contentCellIdentifier)
self.directionalLockEnabled = false
self.backgroundColor = UIColor.whiteColor()
self.delegate = self
self.dataSource = self
self.frame = frame
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setConfig(config: String!) {
var json: JSON = nil;
if let data = config.dataUsingEncoding(NSUTF8StringEncoding) {
json = JSON(data: data);
};
RNCollection.dataSource = json["dataSource"].arrayObject!
RNCollection.sections = json["sections"].intValue
RNCollection.rows = json["rows"].intValue
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let contentCell: RNCollectionCell = collectionView.dequeueReusableCellWithReuseIdentifier(contentCellIdentifier, forIndexPath: indexPath) as! RNCollectionCell
contentCell.textLabel.textColor = UIColor.blackColor()
if indexPath.section == 0 {
contentCell.backgroundColor = UIColor(red: 232/255.0, green: 232/255.0, blue: 232/255.0, alpha: 1.0)
if indexPath.row == 0 {
contentCell.textLabel.font = UIFont.systemFontOfSize(16)
contentCell.textLabel.text = (RNCollection.dataSource[0] as! NSArray)[0] as? String
} else {
contentCell.textLabel.font = UIFont.systemFontOfSize(14)
contentCell.textLabel.text = (RNCollection.dataSource[0] as! NSArray)[indexPath.row] as? String
}
} else {
contentCell.textLabel.font = UIFont.systemFontOfSize(12)
contentCell.backgroundColor = UIColor.whiteColor()
if(indexPath.section % 2 == 0) {
contentCell.backgroundColor = UIColor(red: 234/255.0, green: 234/255.0, blue: 236/255.0, alpha: 1.0)
}
if indexPath.row == 0 {
contentCell.textLabel.text = (RNCollection.dataSource[indexPath.section] as! NSArray)[0] as? String
contentCell.layer.shadowOffset = CGSize(width: 3, height: 3)
contentCell.layer.shadowOpacity = 0.7
contentCell.layer.shadowRadius = 2
} else {
contentCell.textLabel.text = (RNCollection.dataSource[indexPath.section] as! NSArray)[indexPath.row] as? String
}
}
return contentCell
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return RNCollection.rows
}
// MARK - UICollectionViewDataSource
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return RNCollection.sections
}
}
您正在為某個節/行指定自定義項,在其他情況下,您只需設置文本即可。 您應該在else條件中指定所需的/默認的自定義。 考慮代碼的這一部分
if indexPath.row == 0 {
contentCell.textLabel.text = (RNCollection.dataSource[indexPath.section] as! NSArray)[0] as? String
contentCell.layer.shadowOffset = CGSize(width: 3, height: 3)
contentCell.layer.shadowOpacity = 0.7
contentCell.layer.shadowRadius = 2
} else {
contentCell.textLabel.text = (RNCollection.dataSource[indexPath.section] as! NSArray)[indexPath.row] as? String
}
您已在if條件中指定了shadowOffset
, shadowOpacity
和shadowRadius
,但在else條件中忽略了它們。 如果您在else條件下指定外觀,則不會遇到現在遇到的問題。 它應該看起來像這樣
if indexPath.row == 0 {
contentCell.textLabel.text = (RNCollection.dataSource[indexPath.section] as! NSArray)[0] as? String
contentCell.layer.shadowOffset = CGSize(width: 3, height: 3)
contentCell.layer.shadowOpacity = 0.7
contentCell.layer.shadowRadius = 2
} else {
contentCell.textLabel.text = (RNCollection.dataSource[indexPath.section] as! NSArray)[indexPath.row] as? String
contentCell.layer.shadowOffset = 0
contentCell.layer.shadowOpacity = 0
contentCell.layer.shadowRadius = 0
}
如果在所有條件檢查中都正確重置了所有內容,則不會出現此問題。
當行等於0時設置陰影:
if indexPath.row == 0 {...}
但是如果該行不等於零,則在設置陰影后,視圖可以重用該單元格。 解決方案是在row不為0時重置陰影,在您的代碼中您可以執行以下操作(請參見todo):
if indexPath.row == 0 { // Set up shadow here
contentCell.textLabel.text = (RNCollection.dataSource[indexPath.section] as! NSArray)[0] as? String
contentCell.layer.shadowOffset = CGSize(width: 3, height: 3)
contentCell.layer.shadowOpacity = 0.7
contentCell.layer.shadowRadius = 2
} else {
contentCell.textLabel.text = (RNCollection.dataSource[indexPath.section] as! NSArray)[indexPath.row] as? String
//TODO: Remove the shadow here
}
如果您想每次在單元格出現時都保存單元格設置,則應設置方法“ func collectionView(collectionView:UICollectionView,cellForItemAtIndexPath indexPath:NSIndexPath)-> UICollectionViewCell”的所有可能條件。僅當您數據或項目很少。
在Objective-C中,但在Swift中,邏輯應該相同並且不難翻譯。
在RNCollectionCell
。
//These enums may have a better nam, I agree
typedef enum : NSUInteger {
RNCollectionCellStyleColumnTitle,
RNCollectionCellStyleColumnValue,
RNCollectionCellStyleRowTitle,
RNCollectionCellStyleUpperLeftCorner,
} RNCollectionCellStyle;
-(void)titleIt:(NSString *)title forStyle:(RNCollectionCellStyle)style forSection:(NSUInteger)section
{
self.textLabel.textColor = [UIColor blackColor]; //Since it's always the same could be done elsewhere once for all.
//Note I didn't check completely if the case were good, and I didn't add the background color logic, but it should be done here too.
switch (style)
{
case RNCollectionCellStyleColumnTitle:
{
self.textLabel.font = [UIFont systemFontOfSize:12];
self.layer.shadowOffset = CGSizeMake(3, 3);
self.layer.shadowOpacity = 0.7;
self.layer.shadowRadius = 2;
}
break;
case RNCollectionCellStyleColumnValue:
{
self.textLabel.font = [UIFont systemFontOfSize:12];
self.layer.shadowOffset = CGSizeZero;
self.layer.shadowOpacity = 0;
self.layer.shadowRadius = 0;
}
break;
case RNCollectionCellStyleRowTitle:
{
self.textLabel.font = [UIFont systemFontOfSize:14];
self.layer.shadowOffset = CGSizeZero;
self.layer.shadowOpacity = 0;
self.layer.shadowRadius = 0;
}
break;
case RNCollectionCellStyleUpperLeftCorner:
{
self.textLabel.font = [UIFont systemFontOfSize:16];
self.layer.shadowOffset = CGSizeZero;
self.layer.shadowOpacity = 0;
self.layer.shadowRadius = 0;
}
break;
default:
break;
}
self.textLabel.text = title;
}
-(void)prepareForReuse
{
[super prepareForReuse];
self.layer.shadowOffset = CGSizeZero;
self.layer.shadowOpacity = 0;
self.layer.shadowRadius = 0;
}
在RNCollection
:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
RNCollectionCell *contentCell = [collectionView dequeueReusableCellWithReuseIdentifier: contentCellIdentifier forIndexPath:indexPath];
//Here check what style you need to do
//Also, you seems to always do dataSource[indexPath.section][indexPath.row], you just use the "if test values".
[contentCell titleIt:dataSource[indexPath.section][indexPath.row]
forStyle:RNCollectionCellStyleColumnTitle
forSection:[indexPath section]];
return contentCell;
}
如前所述,我沒有根據您的需要檢查所有案例是否正確。 但是,您並沒有“防止單元的重用”,而是對其進行了優化。 您需要在重用之前或設置值時“重置”值。 從理論上講,在prepareForReuse
完成的工作應該足夠了,您不必不必“重置” switch
的圖層效果,但是老實說我沒有檢查它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.