滚动时重复使用一行内的项目
Reuse item inside a row when scrolling
我在 tableView 中有 collectionView。 collectionView 需要水平滚动图片,tableView 需要垂直滚动帖子。当我有 3 rows 时没有问题,但是当我创建 4 rows 时滚动 items 行内。如果我开始滚动第 4 行,滚动会在 行 1 上重复,如果我开始滚动第 1 行,同样的事情 滚动在 行上重复 4.
可能是什么问题以及如何解决?可能是
可以检查.gif 文件。我从名称“Oko”的第 1 行 开始,如果我向下滚动到第 4 行 并滚动右 collectionCell 和 return 在 1 row 我看到下一个图像名称 "City",但必须有名字“Oko”
我的代码:
ViewController:
class PhotoStudiosViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating {
@IBOutlet weak var tableView: UITableView!
var theStudios: [Studio] = []
var filteredStudios: [Studio] = []
var studiosRef: DatabaseReference!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
tableView.estimatedRowHeight = 475
tableView.rowHeight = UITableViewAutomaticDimension
}
override func viewDidLoad() {
super.viewDidLoad()
studiosRef = Database.database().reference(withPath: "PhotoStudios1")
studiosRef.observe(.value, with: { (snapshot) in
for imageSnap in snapshot.children {
let studioObj = Studio(snapshot: imageSnap as! DataSnapshot)
self.theStudios.append(studioObj)
}
self.tableView.reloadData()
})
}
// MARK: - TableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.isActive && searchController.searchBar.text != "" {
return filteredStudios.count
}
return theStudios.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! PhotoStudiosTableViewCell
cell.currentPageNumber.text = "1/\(theStudios[indexPath.row].halls.count)"
if searchController.isActive && searchController.searchBar.text != nil {
cell.theHalls = filteredStudios[indexPath.row].halls
} else {
cell.theHalls = theStudios[indexPath.row].halls
}
cell.nameLabel.text = theStudios[indexPath.row].studioName
cell.addressLabel.text = theStudios[indexPath.row].studioAddress
cell.logoLabel.sd_setImage(with: URL(string: theStudios[indexPath.row].studioLogo))
cell.didSelectAction = {
(innerPath) in
self.showDetailsView(indexPath, cellPath: innerPath)
}
return cell
}
TableViewCell:
class PhotoStudiosTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate, UICollectionViewDelegateFlowLayout {
@IBOutlet weak var button: UIButton!
@IBOutlet weak var logoLabel: UIImageView!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var addressLabel: UILabel!
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var currentPageNumber: UILabel!
var didSelectAction: ((IndexPath) -> ())?
var theHalls: [Hall] = [] {
didSet {
collectionView.reloadData()
}
}
var lastContentOffset = CGPoint.zero
override func prepareForReuse() {
super.prepareForReuse()
resetCollectionView()
}
override func awakeFromNib() {
super.awakeFromNib()
currentPageNumber.layer.zPosition = 2
currentPageNumber.layer.cornerRadius = 15.0
currentPageNumber.clipsToBounds = true
}
func resetCollectionView() {
guard !theHalls.isEmpty else { return }
theHalls = []
collectionView.reloadData()
}
// MARK: - CollectionView
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return theHalls.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! PhotoStudiosCollectionViewCell2
cell.hallName.text = theHalls[indexPath.item].hallName
cell.priceLabel.text = theHalls[indexPath.item].hallPrice
cell.metrslabel.text = theHalls[indexPath.item].hallMetrs
cell.photoStudioImage.sd_setImage(with: URL(string: theHalls[indexPath.item].hallImage))
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
didSelectAction?(indexPath)
}
}
您在单元格中重用了集合视图,这是正确的,但这意味着 contentOffset 也会从之前滚动到的内容中保留下来,当单元格被重用时。当您通过执行以下操作设置单元格时,只需重置 cellForRowAtIndexPath
中的 contentOffset 就足够了:
cell.collectionView.contentOffset = .zero
值得一提的是,我确实看到您的单元格中有一个名为 lastContentOffset
的 属性,它尚未执行任何操作,我怀疑您将尝试使用它来当给定单元格滚出视图时保留给定单元格的偏移量,以便您可以在它返回视图时再次设置它(而不是总是重置)。
如果您要这样做,单元格中的 属性 将不起作用。您需要在包含的视图控制器中与数据模型一起存储每个单元格的偏移量列表。然后,您可以将给定单元格的偏移量保存在 didEndDisplayingCell
中,并将其设置在 cellForRowAtIndexPath
中,而不是像我上面那样设置在 .zero
中。
我在 tableView 中有 collectionView。 collectionView 需要水平滚动图片,tableView 需要垂直滚动帖子。当我有 3 rows 时没有问题,但是当我创建 4 rows 时滚动 items 行内。如果我开始滚动第 4 行,滚动会在 行 1 上重复,如果我开始滚动第 1 行,同样的事情 滚动在 行上重复 4.
可能是什么问题以及如何解决?可能是
可以检查.gif 文件。我从名称“Oko”的第 1 行 开始,如果我向下滚动到第 4 行 并滚动右 collectionCell 和 return 在 1 row 我看到下一个图像名称 "City",但必须有名字“Oko”
我的代码:
ViewController:
class PhotoStudiosViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating {
@IBOutlet weak var tableView: UITableView!
var theStudios: [Studio] = []
var filteredStudios: [Studio] = []
var studiosRef: DatabaseReference!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
tableView.estimatedRowHeight = 475
tableView.rowHeight = UITableViewAutomaticDimension
}
override func viewDidLoad() {
super.viewDidLoad()
studiosRef = Database.database().reference(withPath: "PhotoStudios1")
studiosRef.observe(.value, with: { (snapshot) in
for imageSnap in snapshot.children {
let studioObj = Studio(snapshot: imageSnap as! DataSnapshot)
self.theStudios.append(studioObj)
}
self.tableView.reloadData()
})
}
// MARK: - TableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.isActive && searchController.searchBar.text != "" {
return filteredStudios.count
}
return theStudios.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! PhotoStudiosTableViewCell
cell.currentPageNumber.text = "1/\(theStudios[indexPath.row].halls.count)"
if searchController.isActive && searchController.searchBar.text != nil {
cell.theHalls = filteredStudios[indexPath.row].halls
} else {
cell.theHalls = theStudios[indexPath.row].halls
}
cell.nameLabel.text = theStudios[indexPath.row].studioName
cell.addressLabel.text = theStudios[indexPath.row].studioAddress
cell.logoLabel.sd_setImage(with: URL(string: theStudios[indexPath.row].studioLogo))
cell.didSelectAction = {
(innerPath) in
self.showDetailsView(indexPath, cellPath: innerPath)
}
return cell
}
TableViewCell:
class PhotoStudiosTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate, UICollectionViewDelegateFlowLayout {
@IBOutlet weak var button: UIButton!
@IBOutlet weak var logoLabel: UIImageView!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var addressLabel: UILabel!
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var currentPageNumber: UILabel!
var didSelectAction: ((IndexPath) -> ())?
var theHalls: [Hall] = [] {
didSet {
collectionView.reloadData()
}
}
var lastContentOffset = CGPoint.zero
override func prepareForReuse() {
super.prepareForReuse()
resetCollectionView()
}
override func awakeFromNib() {
super.awakeFromNib()
currentPageNumber.layer.zPosition = 2
currentPageNumber.layer.cornerRadius = 15.0
currentPageNumber.clipsToBounds = true
}
func resetCollectionView() {
guard !theHalls.isEmpty else { return }
theHalls = []
collectionView.reloadData()
}
// MARK: - CollectionView
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return theHalls.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! PhotoStudiosCollectionViewCell2
cell.hallName.text = theHalls[indexPath.item].hallName
cell.priceLabel.text = theHalls[indexPath.item].hallPrice
cell.metrslabel.text = theHalls[indexPath.item].hallMetrs
cell.photoStudioImage.sd_setImage(with: URL(string: theHalls[indexPath.item].hallImage))
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
didSelectAction?(indexPath)
}
}
您在单元格中重用了集合视图,这是正确的,但这意味着 contentOffset 也会从之前滚动到的内容中保留下来,当单元格被重用时。当您通过执行以下操作设置单元格时,只需重置 cellForRowAtIndexPath
中的 contentOffset 就足够了:
cell.collectionView.contentOffset = .zero
值得一提的是,我确实看到您的单元格中有一个名为 lastContentOffset
的 属性,它尚未执行任何操作,我怀疑您将尝试使用它来当给定单元格滚出视图时保留给定单元格的偏移量,以便您可以在它返回视图时再次设置它(而不是总是重置)。
如果您要这样做,单元格中的 属性 将不起作用。您需要在包含的视图控制器中与数据模型一起存储每个单元格的偏移量列表。然后,您可以将给定单元格的偏移量保存在 didEndDisplayingCell
中,并将其设置在 cellForRowAtIndexPath
中,而不是像我上面那样设置在 .zero
中。