【Swift 联动】:两个 TableView 之间的联动,TableView 与 CollectionView 之间的联动前言
之前用 Objective-C 写了一篇联动的 demo 和文章,后来有小伙伴私信我有没有 Swfit 语言的,最近趁晚上和周末学习了一下 Swift 3.0 的语法,写了一个 Swift 的 demo。
思路和Objective-C 版本的联动文章一样,实现的效果也是一样。先来看下效果图。
下面来说下实现两个 TableView 之间联动的主要思路:
先解析数据装入模型。
定义两个 TableView:LeftTableView 和 RightTableView。
fileprivate lazy var leftTableView : UITableView = { let leftTableView = UITableView() leftTableView.delegate = self leftTableView.dataSource = self leftTableView.frame = CGRect(x: 0, y: 0, width: 80, height: ScreenHeight) leftTableView.rowHeight = 55 leftTableView.showsVerticalScrollIndicator = false leftTableView.separatorColor = UIColor.clear leftTableView.register(LeftTableViewCell.self, forCellReuseIdentifier: kLeftTableViewCell) return leftTableView }() fileprivate lazy var rightTableView : UITableView = { let rightTableView = UITableView() rightTableView.delegate = self rightTableView.dataSource = self rightTableView.frame = CGRect(x: 80, y: 64, width: ScreenWidth - 80, height: ScreenHeight - 64) rightTableView.rowHeight = 80 rightTableView.showsVerticalScrollIndicator = false rightTableView.register(RightTableViewCell.self, forCellReuseIdentifier: kRightTableViewCell) return rightTableView }() func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if leftTableView == tableView { let cell = tableView.dequeueReusableCell(withIdentifier: kLeftTableViewCell, for: indexPath) as! LeftTableViewCell let model = categoryData[indexPath.row] cell.nameLabel.text = model.name return cell } else { let cell = tableView.dequeueReusableCell(withIdentifier: kRightTableViewCell, for: indexPath) as! RightTableViewCell let model = foodData[indexPath.section][indexPath.row] cell.setDatas(model) return cell } }先将左边的 TableView 关联右边的 TableView:点击左边的 TableViewCell,右边的 TableView 跳到相应的分区列表头部。
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { if leftTableView == tableView { return nil } let headerView = TableViewHeaderView(frame: CGRect(x: 0, y: 0, width: ScreenWidth, height: 20)) let model = categoryData[section] headerView.nameLabel.text = model.name return headerView }再将右边的 TableView 关联左边的 TableView:标记一下RightTableView 的滚动方向,然后分别在 TableView 分区标题即将展示和展示结束的代理函数里面处理逻辑。
1.在 TableView 分区标题即将展示里面,判断当前的 tableView 是 RightTableView,RightTableView 滑动的方向向上,RightTableView 是会员拖拽而产生滚动的(主要判断RightTableView 是会员拖拽的,还是点击 LeftTableView 滚动的),如果三者都成立,那么 LeftTableView 的选中行就是 RightTableView 的当前 section。
2.在 TableView 分区标题展示结束里面,判断当前的 tableView 是 RightTableView,滑动的方向向下,RightTableView 是会员拖拽而产生滚动的,如果三者都成立,那么 LeftTableView 的选中行就是 RightTableView 的当前 section-1。
// 标记一下 RightTableView 的滚动方向,是向上还是向下 func scrollViewDidScroll(_ scrollView: UIScrollView) { let tableView = scrollView as! UITableView if rightTableView == tableView { isScrollDown = lastOffsetY < scrollView.contentOffset.y lastOffsetY = scrollView.contentOffset.y } } // TableView分区标题即将展示 func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) { // 当前的tableView是RightTableView,RightTableView滚动的方向向上,RightTableView是会员拖拽而产生滚动的((主要判断RightTableView会员拖拽而滚动的,还是点击LeftTableView而滚动的) if (rightTableView == tableView) && !isScrollDown && rightTableView.isDragging { selectRow(index: section) } } // TableView分区标题展示结束 func tableView(_ tableView: UITableView, didEndDisplayingHeaderView view: UIView, forSection section: Int) { // 当前的tableView是RightTableView,开题报告,RightTableView滚动的方向向下,RightTableView是会员拖拽而产生滚动的((主要判断RightTableView会员拖拽而滚动的,还是点击LeftTableView而滚动的) if (rightTableView == tableView) && isScrollDown && rightTableView.isDragging { selectRow(index: section + 1) } } // 当拖动右边TableView的时候,处理左边TableView private func selectRow(index : Int) { leftTableView.selectRow(at: IndexPath(row: index, section: 0), animated: true, scrollPosition: .top) }这样就实现了两个 TableView 之间的联动,是不是很简单。
二、TableView 与 CollectionView 之间的联动#p#分页标题#e#TableView 与 CollectionView 之间的联动与两个 TableView 之间的联动逻辑类似。
下面说下实现 TableView 与 CollectionView 之间的联动的主要思路:
还是一样,开题报告,先解析数据装入模型。
定义一个 TableView,一个 CollectionView。
fileprivate lazy var tableView : UITableView = { let tableView = UITableView() tableView.delegate = self tableView.dataSource = self tableView.frame = CGRect(x: 0, y: 0, width: 80, height: ScreenHeight) tableView.rowHeight = 55 tableView.showsVerticalScrollIndicator = false tableView.separatorColor = UIColor.clear tableView.register(LeftTableViewCell.self, forCellReuseIdentifier: kLeftTableViewCell) return tableView }() fileprivate lazy var collectionView : UICollectionView = { let flowlayout = LJCollectionViewFlowLayout() flowlayout.scrollDirection = .vertical flowlayout.minimumLineSpacing = 2 flowlayout.minimumInteritemSpacing = 2 flowlayout.itemSize = CGSize(width: (ScreenWidth - 80 - 4 - 4) / 3, height: (ScreenWidth - 80 - 4 - 4) / 3 + 30) flowlayout.headerReferenceSize = CGSize(width: ScreenWidth, height: 30) let collectionView = UICollectionView(frame: CGRect.init(x: 2 + 80, y: 2 + 64, width: ScreenWidth - 80 - 4, height: ScreenHeight - 64 - 4), collectionViewLayout: flowlayout) collectionView.delegate = self collectionView.dataSource = self collectionView.showsVerticalScrollIndicator = false collectionView.showsHorizontalScrollIndicator = false collectionView.backgroundColor = UIColor.clear collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: kCollectionViewCell) collectionView.register(CollectionViewHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: kCollectionViewHeaderView) return collectionView }() func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: kLeftTableViewCell, for: indexPath) as! LeftTableViewCell let model = dataSource[indexPath.row] cell.nameLabel.text = model.name return cell } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: kCollectionViewCell, for: indexPath) as! CollectionViewCell let model = collectionDatas[indexPath.section][indexPath.row] cell.setDatas(model) return cell }先将 TableView 关联 CollectionView,点击 TableViewCell,右边的 CollectionView 跳到相应的分区列表头部。
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { selectIndex = indexPath.row collectionView.scrollToItem(at: IndexPath(row: 0, section: selectIndex), at: .top, animated: true) tableView.scrollToRow(at: IndexPath(row: selectIndex, section: 0), at: .top, animated: true) }再将 CollectionView 关联 TableView,标记一下 RightTableView 的滚动方向,然后分别在 CollectionView 分区标题即将展示和展示结束的代理函数里面处理逻辑。
#p#分页标题#e#
1.在 CollectionView 分区标题即将展示里面,判断 当前 CollectionView 滚动的方向向上, CollectionView 是会员拖拽而产生滚动的(主要是判断 CollectionView 是会员拖拽而滚动的,还是点击 TableView 而滚动的),如果二者都成立,那么 TableView 的选中行就是 CollectionView 的当前 section。
2.在 CollectionView 分区标题展示结束里面,判断当前 CollectionView 滚动的方向向下, CollectionView 是会员拖拽而产生滚动的,如果二者都成立,那么 TableView 的选中行就是 CollectionView 的当前 section-1。
// 标记一下 CollectionView 的滚动方向,是向上还是向下 func scrollViewDidScroll(_ scrollView: UIScrollView) { if collectionView == scrollView { isScrollDown = lastOffsetY < scrollView.contentOffset.y lastOffsetY = scrollView.contentOffset.y } } // CollectionView 分区标题即将展示 func collectionView(_ collectionView: UICollectionView, willDisplaySupplementaryView view: UICollectionReusableView, forElementKind elementKind: String, at indexPath: IndexPath) { // 当前 CollectionView 滚动的方向向上,CollectionView 是会员拖拽而产生滚动的(主要是判断 CollectionView 是会员拖拽而滚动的,还是点击 TableView 而滚动的) if !isScrollDown && collectionView.isDragging { selectRow(index: indexPath.section) } } // CollectionView 分区标题展示结束 func collectionView(_ collectionView: UICollectionView, didEndDisplayingSupplementaryView view: UICollectionReusableView, forElementOfKind elementKind: String, at indexPath: IndexPath) { // 当前 CollectionView 滚动的方向向下,CollectionView 是会员拖拽而产生滚动的(主要是判断 CollectionView 是会员拖拽而滚动的,还是点击 TableView 而滚动的) if isScrollDown && collectionView.isDragging { selectRow(index: indexPath.section + 1) } } // 当拖动 CollectionView 的时候,处理 TableView private func selectRow(index : Int) { tableView.selectRow(at: IndexPath(row: index, section: 0), animated: true, scrollPosition: .middle) }TableView 与 CollectionView 之间的联动就这么实现了,是不是也很简单。
github地址:https://github.com/leejayID/Linkage-Swift