web-dev-qa-db-ja.com

ビューの最初のロード時にUICollectionViewCellを事前に選択/強調表示

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;
}
17
DevC

viewDidAppear内:

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

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で使用する必要があります

9

For Swiftの場合

このオーバーロード内で_collectionView.selectItem_を使用しますcollectionView(UICollectionView, IndexPath)

これは私のコードです。このコードでは、_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)
}
_
8
Hamed

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

次に、カスタムコレクションビューを初期化するときに、必要なIndexPathinitialSelectedIndexPathに設定するだけです

6
Anatoly

私にとっては、viewDidAppear:秒を選択して、ユーザーに両方の状態(選択されていない状態と選択されている状態)が表示されるようにします。これを避けるために、viewWillAppear:代わりに、魅力のように機能しました

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

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)
}
4
Phung Du
    [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];
2
wlixcc

最初にセルを選択するためのSwiftコード

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などのデリゲート関数は呼び出されません。

1
Ashwin Felix

私の場合。私はUICollectionViewクラスをGeneric typesのサブクラスで解決しました

// ******************************************
//
// 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
}()
0
Stephen Chen