繁体   English   中英

如何防止uicollectionview的单元重用

[英]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条件中指定了shadowOffsetshadowOpacityshadowRadius ,但在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM