两个UITableView垂直同步滑动,并且右边的列表能水平滑动,左边固定只能上下滑动,这个需求不常见。多见于了财经App中,左边是固定的行情名称和code,右边则有很多相关的信息展示,比如:当前值,开盘价、最高价、最低价、昨收价、收盘价、涨跌、涨跌幅等。经过构思,大致分析如下:
1、左边是UITableView,与当前设备的同宽高。实际只展示一列数据,比如:美元USD
2、通过addSubView 为左边列表添加一个ScrollView,其宽度为整个设备宽度减去左边列表实际占用的宽度(假如列宽为:100pt),高度为总数据条数与列高度的乘积(即为左边列表的contentSize 的高度)。
3、在右边的ScrollView 中addSubView 一个UITableView,用于显示右边列表信息。其宽度是右边信息列的宽度(一般会比 ScrollView 的width 要宽,否则水平滚动就滚不起来了),其高度与ScrollView 同高。由于TableView 要水平滚动必须要要加到ScrollView 中,但这也会导致该列表的列重用机制被破坏。
初步效果图如下:
参考代码如下:
//
// TableViewController.swift
// SwiftAppDeme
//
// Created by apple on 2019/7/7.
// Copyright © 2019 yimiSun. All rights reserved.
//
import UIKit
import SnapKit
/**
* UITableView 例子
*/
class TableViewController: BaseViewController,UITableViewDelegate,UITableViewDataSource {
let cell_count:Int = 30
let cell_height:CGFloat = 50
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.initView()
}
//MARK: - initView
private func initView() -> Void {
//MARK:导航
self.initNavgationBar(isBottomLine: false,
isShadow: true)
//MARK:标题
self.initViewControllerTitle(strTitle: "UITableView")
//MARK:列表
self.view.addSubview(self.leftListTableView)
self.leftListTableView.addSubview(self.scrollViewRight)
//缺点:加到 ScrollView 的列表重用机制被破坏
self.scrollViewRight.addSubview(self.listTableView)
self.view.sendSubviewToBack(self.leftListTableView)
}
//MARK: - UITableViewDelegate、UITabelViewDataSource
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
//MARK:组头、组尾
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return CGFloat.leastNormalMagnitude
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return CGFloat.leastNormalMagnitude
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return nil
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return nil
}
//MARK:列
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cell_count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return cell_height
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == self.leftListTableView {
var cell:LeftTableCell? = tableView.dequeueReusableCell(withIdentifier: LeftTableCell.cell_identify) as? LeftTableCell
if cell == nil {
cell = LeftTableCell.init(style: .default, reuseIdentifier: LeftTableCell.cell_identify)
}
cell?.initBindCellData(strInfo: "\(indexPath.row).左边列信息")
return cell!
}
else{
var cell:RightTableCell? = tableView.dequeueReusableCell(withIdentifier: RightTableCell.cell_identify) as? RightTableCell
if cell == nil {
cell = RightTableCell.init(style: .default, reuseIdentifier: RightTableCell.cell_identify)
}
cell?.initBindCellDataFor(Index: indexPath.row)
return cell!
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
defer {
tableView.deselectRow(at: indexPath, animated: true)
}
print("leftListTableView.visibleCells.count:\(self.leftListTableView.visibleCells.count)")
print("listTableView.visibleCells.count:\(self.listTableView.visibleCells.count)")
}
//MARK: - 侧滑
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
//备注
let remark:UITableViewRowAction = UITableViewRowAction.init(style: .destructive, title: "备注") { (_action:UITableViewRowAction, _indexPath:IndexPath) in
print("我是备注")
}
remark.backgroundColor = UIColor.init().colorFromHexInt(hex: 0x01A1EF)
//删除
let delete:UITableViewRowAction = UITableViewRowAction.init(style: .default, title: "删除") { (_action:UITableViewRowAction, _indexPath:IndexPath) in
print("我是删除")
}
delete.backgroundColor = UIColor.init().colorFromHexInt(hex: 0xff544b)
return [delete,remark]
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// if tableView == self.listTableView {
// return true
// }
return false
}
//MARK: - lazy load
private lazy var leftListTableView:UITableView = {
let y = K_APP_NAVIGATION_BAR_HEIGHT
let h = K_APP_HEIGHT - y - K_APP_TABBAR_HEIGHT
let _tb = UITableView.init(frame: .init(x: 0, y: y,
width:K_APP_WIDTH,
height: h),
style: UITableView.Style.plain)
_tb.backgroundColor = UIColor.clear
_tb.isScrollEnabled = true
_tb.showsVerticalScrollIndicator = false
_tb.showsHorizontalScrollIndicator = false
//分割线
_tb.separatorStyle = .singleLine
_tb.separatorColor = K_APP_SPLIT_LINE_COLOR
//行选中
_tb.allowsSelection = true
_tb.allowsMultipleSelection = false
//表头、表尾
_tb.tableHeaderView = UIView.init(frame: .zero)
_tb.tableFooterView = UIView.init(frame: .zero)
_tb.delegate = self
_tb.dataSource = self
//防止顶部空白
if #available(iOS 11.0, *) {
_tb.contentInsetAdjustmentBehavior = UIScrollView.ContentInsetAdjustmentBehavior.never
}
else {
self.automaticallyAdjustsScrollViewInsets = false
}
//注册
_tb.register(LeftTableCell.classForCoder(),
forCellReuseIdentifier: LeftTableCell.cell_identify)
return _tb
}()
private lazy var scrollViewRight:UIScrollView = {
let th = CGFloat.init(cell_count) * cell_height
let _s = UIScrollView.init(frame: CGRect.init(x: 0.3 * K_APP_WIDTH,
y: 0,
width: 0.7 * K_APP_WIDTH,
height: th))
_s.contentSize = CGSize.init(width: RightTableCell.cell_width, height: th)
_s.backgroundColor = UIColor.clear
_s.isUserInteractionEnabled = true
_s.showsVerticalScrollIndicator = false
_s.showsHorizontalScrollIndicator = false
return _s
}()
private lazy var listTableView:UITableView = {
let th = CGFloat.init(cell_count) * cell_height
let _tb = UITableView.init(frame: CGRect.init(x: 0, y: 0,
width: RightTableCell.cell_width,
height: th),
style: UITableView.Style.plain)
_tb.backgroundColor = UIColor.clear
_tb.isScrollEnabled = false
_tb.isUserInteractionEnabled = false
_tb.showsVerticalScrollIndicator = false
_tb.showsHorizontalScrollIndicator = false
//分割线
_tb.separatorStyle = .none
_tb.separatorColor = UIColor.clear
//行选中
_tb.allowsSelection = false
_tb.allowsMultipleSelection = false
//表头、表尾
_tb.tableHeaderView = UIView.init(frame: .zero)
_tb.tableFooterView = UIView.init(frame: .zero)
_tb.delegate = self
_tb.dataSource = self
//防止顶部空白
if #available(iOS 11.0, *) {
_tb.contentInsetAdjustmentBehavior = UIScrollView.ContentInsetAdjustmentBehavior.never
}
else {
self.automaticallyAdjustsScrollViewInsets = false
}
//注册
_tb.register(RightTableCell.classForCoder(), forCellReuseIdentifier: RightTableCell.cell_identify)
return _tb
}()
}
//MARK: - 左边列
class LeftTableCell: UITableViewCell {
static let cell_identify:String = "left_cell_identify"
static let cell_width:CGFloat = 0.3 * K_APP_WIDTH
//MARK: - override
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.initView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//MARK: - initView
private func initView(){
self.backgroundColor = UIColor.clear
self.addSubview(self.labInfo)
self.labInfo.snp.makeConstraints { make in
make.left.equalTo(20)
make.right.equalTo(-20)
make.height.equalTo(21)
make.centerY.equalTo(self.centerY)
}
}
/** 列数据绑定 */
public func initBindCellData(strInfo:String) {
self.labInfo.text = strInfo
}
//MARK: - lazy load
private lazy var labInfo:YYLabel = {
let _l = YYLabel.init()
_l.textAlignment = .left
_l.textColor = UIColor.black
_l.font = UIFont.systemFont(ofSize: 14)
return _l
}()
}
//MARK: - 右边列
class RightTableCell:UITableViewCell {
static let cell_identify:String = "right_cell_identify"
static let cell_width:CGFloat = 600
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.initView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//MARK: - initView
private func initView(){
self.backgroundColor = UIColor.clear
self.addSubview(self.labInfo)
self.labInfo.snp.makeConstraints { make in
make.left.equalTo(30)
make.width.equalTo(180)
make.height.equalTo(21)
make.centerY.equalTo(self.centerY)
}
self.addSubview(self.labInfo2)
self.labInfo2.snp.makeConstraints { make in
make.left.equalTo(self.labInfo.snp.right).offset(20)
make.width.equalTo(180)
make.height.equalTo(21)
make.centerY.equalTo(self.centerY)
}
self.addSubview(self.labInfo3)
self.labInfo3.snp.makeConstraints { make in
make.left.equalTo(self.labInfo2.snp.right).offset(20)
make.width.equalTo(180)
make.height.equalTo(21)
make.centerY.equalTo(self.centerY)
}
}
/** 列数据绑定 */
public func initBindCellDataFor(Index ix:Int) {
self.labInfo.text = "\(ix).右边[a]"
self.labInfo2.text = "右边[b]"
self.labInfo3.text = "右边[c]"
}
//MARK: - lazy load
private lazy var labInfo:YYLabel = {
let _l = YYLabel.init()
_l.textAlignment = .left
_l.textColor = UIColor.black
_l.font = UIFont.systemFont(ofSize: 14)
return _l
}()
private lazy var labInfo2:YYLabel = {
let _l = YYLabel.init()
_l.textAlignment = .center
_l.textColor = UIColor.black
_l.font = UIFont.systemFont(ofSize: 14)
return _l
}()
private lazy var labInfo3:YYLabel = {
let _l = YYLabel.init()
_l.textAlignment = .center
_l.textColor = UIColor.black
_l.font = UIFont.systemFont(ofSize: 14)
return _l
}()
}
目前暂未找到更好的方法,能保留两个TableView 的列重用。如有其他更好的方案欢迎留言交流