簡體   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