【问题标题】:pre select/highlight UICollectionViewCell on first load of view在第一次加载视图时预选择/突出显示 UICollectionViewCell
【发布时间】:2015-04-23 14:34:26
【问题描述】:

我试图在 UICollectionView 中预选第一个对象/UICollectionViewCell?我试过了:

self.dateCollectionView.allowsMultipleSelection=NO;

[self.dateCollectionView selectItemAtIndexPath:0 animated:YES scrollPosition:UICollectionViewScrollPositionLeft];
[self collectionView:self.dateCollectionView didSelectItemAtIndexPath:0];
[self.dateCollectionView reloadData];

viewDidLoad.

这是我的UICollectionView 方法;

 -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{

  return self.titles.count;
 }

 -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

    UICollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
    cell.backgroundColor= [UIColor clearColor];
    UILabel * dateLabel = (UILabel *)[cell viewWithTag:1];
    UILabel * subText = (UILabel *)[cell viewWithTag:2];
    subText.text=self.titles[indexPath.row];
    subText.adjustsFontSizeToFitWidth=YES;
    if (cell.selected) {
        cell.backgroundColor = [UIColor blueColor]; // highlight selection
    }
    else
    {
        cell.backgroundColor = [UIColor redColor]; // Default color
    }
    return cell;
}

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath  {

    UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
    datasetCell.backgroundColor = [UIColor blueColor]; // highlight selection
}

-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {

 UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
datasetCell.backgroundColor = [UIColor redColor]; // Default color
}

- (BOOL)collectionView:(UICollectionView *)collectionView
 shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (BOOL)collectionView:(UICollectionView *)collectionView
 shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath;
{
    return YES;
}

【问题讨论】:

    标签: ios objective-c uicollectionview uicollectionviewcell


    【解决方案1】:

    viewDidAppear:

    NSIndexPath *indexPathForFirstRow = [NSIndexPath indexPathForRow:0 inSection:0];
    [self.dateCollectionView selectItemAtIndexPath:indexPathForFirstRow animated:NO scrollPosition:UICollectionViewScrollPositionNone];
    [self collectionView:self.dateCollectionView didSelectItemAtIndexPath:indexPathForFirstRow];
    

    【讨论】:

      【解决方案2】:

      对于 Swift 3.0.1 你可以试试这个:

      self.collectionView.selectItem(at: indexPath, animated: true, scrollPosition: [])
      

      self.collectionView.selectItem(at: indexPath, animated: true, scrollPosition: UICollectionViewScrollPosition(rawValue: 0))
      

      对于 Objective-C 你可以试试这个:

      self.collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone];
      

      注意:你应该在viewDidAppear

      中使用它

      【讨论】:

        【解决方案3】:

        对于 swift 3

        在这个重载collectionView(UICollectionView, IndexPath)中使用collectionView.selectItem

        这是我的代码,在此代码中,我预先选择了带有indexPath.row = 0 的行

        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = ScenarioCollectionView.dequeueReusableCell(withReuseIdentifier: "ReuseScenarioCollectionViewCell", for: indexPath as IndexPath) as! ScenarioCollectionViewCell
        
            if (indexPath.row == 0){
                collectionView.selectItem(at: indexPath, animated: true, scrollPosition: UICollectionViewScrollPosition.centeredHorizontally)
                cell.layer.borderColor=UIColor.gray.cgColor        
            }else{
                cell.layer.borderColor=UIColor.white.cgColor
            }
            return cell
        }
        
        
        func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            let cell = collectionView.cellForItem(at: indexPath)
            cell?.layer.borderColor = UIColor.gray.cgColor
                }
        
        func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
            let cell = collectionView.cellForItem(at: indexPath as IndexPath)
            cell?.layer.borderColor = UIColor.white.cgColor
            collectionView.deselectItem(at: indexPath, animated: true)
        }
        

        【讨论】:

          【解决方案4】:

          我通过子类化UICollectionView 并在layoutSubviews 中选择需要的项目解决了这个问题:

          class InitialSelectionCollectionView: UICollectionView {
          
             var initialSetupPerformed: Bool = false
             var initialSelectedIndexPath: IndexPath!
          
             override func layoutSubviews() {
                 super.layoutSubviews()
          
                 if !initialSetupPerformed && initialSelectedIndex != nil{
                     selectItem(at: initialSelectedIndexPath, animated: false, scrollPosition: .centeredHorizontally)
          
                     initialSetupPerformed = true
                 }
             }
          }
          

          然后,当您初始化自定义集合视图时,只需将需要的 IndexPath 设置为 initialSelectedIndexPath

          【讨论】:

            【解决方案5】:

            对我来说,将其放入 viewDidAppear: 会导致第二次选择,因此用户将看到两种状态(即未选择和已选择)。 为了避免这种情况,我把它放在viewWillAppear: 中,并像魅力一样工作

            override func viewWillAppear(_ animated: Bool) {
                let selectedIndexPath = IndexPath(item: 0, section: 0)
                collectionView.selectItem(at: selectedIndexPath, animated: false, scrollPosition: .left)
            }
            

            【讨论】:

              【解决方案6】:

              对于 Swift 3:

              override func viewDidAppear(_ animated: Bool) {
                  super.viewDidAppear(animated)
                  //auto selected 1st item
                  let indexPathForFirstRow = IndexPath(row: 0, section: 0)
                  self.collectionView?.selectItem(at: indexPathForFirstRow, animated: true, scrollPosition: .top)
              }
              

              【讨论】:

                【解决方案7】:
                    [self.collectionView reloadData];
                    [self.collectionView layoutIfNeeded]; //important
                    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
                    [self.collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
                    [self collectionView:self.collectionView didSelectItemAtIndexPath:indexPath];
                

                【讨论】:

                • layoutIfNeeded 拯救了我的一天!
                【解决方案8】:

                用于初始选择单元格的快速代码

                func selectinitialCell() {
                
                    let cell = venueTypeCollectionView.cellForItemAtIndexPath(NSIndexPath(forItem: 0, inSection: 0)) as! SearchTypeCollectionViewCell
                    self.indexPathOfSelectedItem = NSIndexPath(forItem: 0, inSection: 0)
                    cell.venueType.textColor = UIColor.whiteColor()
                    cell.selected = true
                }
                

                但这不会调用didSelectItemAtIndexPath、didDeselectItemAtIndexPath等委托函数。

                【讨论】:

                  【解决方案9】:

                  就我而言。我通过带有Generic typesUICollectionView 类的子类解决了它

                  // ******************************************
                  //
                  // MARK: - Config injection, Extend whatever you want
                  //
                  // ******************************************
                  struct CCCollectionViewConfig {
                      var itemSize: CGSize?
                      var minimumInteritemSpacing: CGFloat?
                      var minimumLineSpacing: CGFloat?
                      var allowsDefaultSelection: Bool = true
                  }
                  
                  // ******************************************
                  //
                  // MARK: - Generic CCCollectionView
                  //
                  // ******************************************
                  final class CCCollectionView<T, Cell: UICollectionViewCell>: UICollectionView, UICollectionViewDataSource, UICollectionViewDelegate {
                  
                      typealias SelectHandler = (T, IndexPath?) -> Void
                  
                      typealias CellConfigure = (Cell, T) -> Void
                  
                      var contents: [T] = [] {
                          didSet {
                              DispatchQueue.main.async {
                                  self.reloadData()
                                  self.selectedIndexPath = IndexPath(item: (self.config.allowsDefaultSelection) ? 0 : -1, section: 0)
                              }
                          }
                      }
                  
                      var configure: CellConfigure
                  
                      var selectHandler: SelectHandler
                  
                      var selectedIndexPath: IndexPath
                  
                      private var config: CCCollectionViewConfig
                  
                      private let identifier = "identifier"
                  
                      init(contents: [T], config: CCCollectionViewConfig, configure: @escaping CellConfigure, selectHandler: @escaping SelectHandler) {
                  
                          self.config = config
                          self.contents = contents
                          self.configure = configure
                          self.selectHandler = selectHandler
                          self.selectedIndexPath = IndexPath(item: (config.allowsDefaultSelection) ? 0 : -1, section: 0)
                  
                          let layout = UICollectionViewFlowLayout()
                  
                          if let size = config.itemSize {
                              layout.itemSize = size
                          }
                  
                          layout.minimumInteritemSpacing = config.minimumInteritemSpacing ?? 0
                          layout.minimumLineSpacing = config.minimumLineSpacing ?? 0
                          layout.scrollDirection = .vertical
                          layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
                  
                          super.init(frame: .zero, collectionViewLayout: layout)
                  
                          setup()
                      }
                  
                      required init?(coder aDecoder: NSCoder) {
                          fatalError("init(coder:) has not been implemented")
                      }
                  
                      private func setup() {
                          register(Cell.self, forCellWithReuseIdentifier: identifier)
                  
                          super.delegate = self
                          super.dataSource = self
                  
                          allowsMultipleSelection = false
                          isScrollEnabled = false
                          backgroundColor = .clear
                      }
                  
                      // ******************************************
                      //
                      // MARK: - UICollectionViewDataSource, UICollectionViewDelegate
                      //
                      // ******************************************
                  
                      func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
                          return contents.count
                      }
                  
                      func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
                          let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! Cell
                          cell.isSelected = (selectedIndexPath == indexPath)
                          let content = contents[indexPath.row]
                          configure(cell, content)
                          return cell
                      }
                  
                      func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
                  
                          let content = contents[indexPath.row]
                          selectHandler(content, indexPath)
                  
                          /// If selected item is equal to current selected item, ignore it
                          if selectedIndexPath == indexPath {
                              return
                          }
                  
                          /// Handle selected cell
                          let selectedCell = collectionView.cellForItem(at: indexPath)
                          selectedCell?.isSelected = true
                  
                          /// Handle deselected cell
                          let deselectItem = collectionView.cellForItem(at: selectedIndexPath)
                          deselectItem?.isSelected = false
                  
                          selectedIndexPath = indexPath
                      }
                  }
                  
                  // ******************************************
                  //
                  // MARK: - CollectionViewCell
                  //
                  // ******************************************
                  final class CCCollectionViewCell: UICollectionViewCell {
                  
                      var title: String = "" {
                          didSet {
                              titleLabel.text = title
                          }
                      }
                  
                      private let titleLabel: UILabel = {
                          let label = UILabel()
                          return label
                      }()
                  
                  
                      var _isSelected: Bool = false
                      override var isSelected: Bool {
                          get {
                              return _isSelected
                          }
                          set(newValue) {
                              _isSelected = newValue
                              updateSelection()
                          }
                      }
                  
                      private func updateSelection() -> Void {
                          contentView.layer.borderColor = isSelected ? UIColor.red.cgColor : UIColor.green.cgColor
                      }
                  
                      override init(frame: CGRect) {
                          super.init(frame: frame)
                          contentView.addSubview(titleLabel)
                          contentView.layer.cornerRadius = 2.0
                          contentView.layer.borderWidth = 2.0
                      }
                  
                      required init?(coder aDecoder: NSCoder) {
                          fatalError("init(coder:) has not been implemented")
                      }
                  }
                  

                  然后在你的 ViewController 中使用它

                  private let fakeContents = Array(repeating: "123123", count: 40)
                  
                  /// Collection View Config
                  private lazy var config: CCCollectionViewConfig = {
                      return CCCollectionViewConfig(itemSize: CGSize(width: 100, height: 30),
                                                    minimumInteritemSpacing: 4.0,
                                                    minimumLineSpacing: 4.0)
                  }()
                  
                  /// Collection View Config
                  private lazy var collectionView: CCCollectionView<String, CCCollectionViewCell> = {
                      let cv = CCCollectionView<String, CCCollectionViewCell>(contents: fakeContents, config: config, configure: { (cell: CCCollectionViewCell, content) in
                          cell.title = content
                      }) { [weak self] (content, indexPath) in
                          guard let self = self else { return }
                          guard let row = indexPath?.row else { return }
                      }
                      return cv
                  }()
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-08-20
                    • 1970-01-01
                    • 2012-12-22
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-07-26
                    • 2014-02-07
                    相关资源
                    最近更新 更多