pre select/highlight UICollectionViewCell 在第一次加载视图时
pre select/highlight UICollectionViewCell on first load of view
我正在尝试预选 UICollectionView 中的第一个 object/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;
}
在viewDidAppear
中:
NSIndexPath *indexPathForFirstRow = [NSIndexPath indexPathForRow:0 inSection:0];
[self.dateCollectionView selectItemAtIndexPath:indexPathForFirstRow animated:NO scrollPosition:UICollectionViewScrollPositionNone];
[self collectionView:self.dateCollectionView didSelectItemAtIndexPath:indexPathForFirstRow];
对于 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)
}
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等委托函数。
对于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
中使用它
为swift3
使用collectionView.selectItem
with-in这个重载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)
}
对我来说,把它放在 viewDidAppear:
会导致 select 秒,所以用户会看到两种状态(即未 selected 和 selected ).
为避免这种情况,我将其放在 viewWillAppear:
中,效果很好
override func viewWillAppear(_ animated: Bool) {
let selectedIndexPath = IndexPath(item: 0, section: 0)
collectionView.selectItem(at: selectedIndexPath, animated: false, scrollPosition: .left)
}
我通过子类化 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
[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];
以我为例。我通过 subclass a UICollectionView
class 和 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
}()
我正在尝试预选 UICollectionView 中的第一个 object/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;
}
在viewDidAppear
中:
NSIndexPath *indexPathForFirstRow = [NSIndexPath indexPathForRow:0 inSection:0];
[self.dateCollectionView selectItemAtIndexPath:indexPathForFirstRow animated:NO scrollPosition:UICollectionViewScrollPositionNone];
[self collectionView:self.dateCollectionView didSelectItemAtIndexPath:indexPathForFirstRow];
对于 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)
}
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等委托函数。
对于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
中使用它为swift3
使用collectionView.selectItem
with-in这个重载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)
}
对我来说,把它放在 viewDidAppear:
会导致 select 秒,所以用户会看到两种状态(即未 selected 和 selected ).
为避免这种情况,我将其放在 viewWillAppear:
中,效果很好
override func viewWillAppear(_ animated: Bool) {
let selectedIndexPath = IndexPath(item: 0, section: 0)
collectionView.selectItem(at: selectedIndexPath, animated: false, scrollPosition: .left)
}
我通过子类化 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
[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];
以我为例。我通过 subclass a UICollectionView
class 和 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
}()