【Swift】TableView显示多列数据,锁定第一列位置
import Foundation import JXCategoryView class LQQuoteDetailCategoryController: UIViewController ,UIGestureRecognizerDelegate{ var listViewDidScrollCallback: ((UIScrollView) -> ())? var kOriginX = 120 var titleTableView: UITableView! //标题TableView var infoTableView: UITableView! //内容TableView var contentView: UIScrollView! //内容容器 var infoArr = [LQQuotedDetailModel]() var titleArr = ["当前价","涨跌","幅度","买价","卖价","昨收","成交量","最高价","开盘价","最低价"] var lastContentOffSetX : CGFloat = 0 var lastContentOffSetY : CGFloat = 0 var currentScrollView : UIScrollView! override func viewDidLoad() { super.viewDidLoad() configureView() } func configureView() { contentView = UIScrollView(frame: CGRect(x: kOriginX, y: 0, width: Int(kScreen_Width) - kOriginX, height: Int(kScreen_Height))) contentView.delegate = self contentView.showsVerticalScrollIndicator = false contentView.showsHorizontalScrollIndicator = false contentView.contentSize = CGSize(width: Int(titleArr.count * 100), height: Int(kScreen_Height)) contentView.bounces = true view.addSubview(contentView) let model1 = LQQuotedDetailModel(variety: "黄金延期", currentPrice: 373.90, upAndDownPrice: -1.71, scope: -0.46, buyPrice: 373.70, salePrice: 373.95, yesterdayHarvest: 375.36, topPrice: 375.19, openingPrice: 374.47, bottomPrice: 372.90,turnover: 132.4) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) infoArr.append(model1) let titleLabel : UILabel = self.quickCreateLabel(withLeft: 0, width: CGFloat(kOriginX), title: "类种")! titleLabel.backgroundColor = .white titleLabel.font = UIFont.boldSystemFont(ofSize: 15) self.view.addSubview(titleLabel) for i in 0..<titleArr.count { let x = CGFloat(i * 100) let label = quickCreateLabel(withLeft: x, width: 100, title: titleArr[i]) label?.textAlignment = .center label?.backgroundColor = .white label?.font = UIFont.boldSystemFont(ofSize: 15) contentView.addSubview(label!) } titleTableView = UITableView(frame: CGRect(x: 0, y: 50, width: kOriginX, height: Int(kScreen_Height - kTopBarSafeMargin)), style: .plain) titleTableView.dataSource = self titleTableView.delegate = self titleTableView.showsVerticalScrollIndicator = false titleTableView.showsHorizontalScrollIndicator = false titleTableView.separatorStyle = .none titleTableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 150, right: 0) view.addSubview(titleTableView!) infoTableView = UITableView(frame: CGRect(x: 0, y: 50, width: titleArr.count * 100, height: Int(kScreen_Height - kTopBarSafeMargin)), style: .plain) infoTableView.delegate = self infoTableView.dataSource = self infoTableView.showsVerticalScrollIndicator = false infoTableView.showsHorizontalScrollIndicator = true infoTableView.separatorStyle = .none infoTableView.register(LQQuoteInfoTableViewCell.classForCoder(), forCellReuseIdentifier: "LQQuoteInfoTableViewCell") infoTableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 150, right: 0) contentView.addSubview(infoTableView) } @objc func enterQuoteDetailListAction() { let quoteDetail = LQQuoteDetailListController() self.navigationController?.pushViewController(quoteDetail, animated: true) } func quickCreateLabel(withLeft left: CGFloat, width: CGFloat, title: String?) -> UILabel? { let label = UILabel(frame: CGRect(x: left, y: 10, width: width, height: 50)) label.text = title label.textAlignment = .center return label } } extension LQQuoteDetailCategoryController : UITableViewDelegate,UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return infoArr.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let model = self.infoArr[indexPath.row] if tableView == self.titleTableView { var cell = tableView.dequeueReusableCell(withIdentifier: "titleTable") if cell == nil { cell = UITableViewCell(style: .default, reuseIdentifier: "titleTable") } cell?.textLabel?.textAlignment = .center cell?.selectionStyle = .none cell?.textLabel?.text = model.variety cell?.textLabel?.textColor = UIColor.black cell?.textLabel?.font = UIFont.systemFont(ofSize: 14) if indexPath.row % 2 == 1 { cell!.backgroundColor = UIColor(red: 218 / 255.0, green: 218 / 255.0, blue: 218 / 255.0, alpha: 1) } else { cell!.backgroundColor = UIColor.white } return cell! } else { let cell = tableView.dequeueReusableCell(withIdentifier: "LQQuoteInfoTableViewCell") as! LQQuoteInfoTableViewCell if indexPath.row % 2 == 1 { cell.backgroundColor = UIColor(red: 218 / 255.0, green: 218 / 255.0, blue: 218 / 255.0, alpha: 1) } else { cell.backgroundColor = .white } cell.configureModel(model: model) return cell } } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 40 } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { } func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { self.currentScrollView = scrollView } func scrollViewDidScroll(_ scrollView: UIScrollView) { if scrollView == self.titleTableView && self.currentScrollView == scrollView{ self.infoTableView.setContentOffset(CGPoint(x: self.infoTableView.contentOffset.x, y: self.titleTableView.contentOffset.y), animated: false) } if scrollView == self.infoTableView && self.currentScrollView == scrollView { self.titleTableView.setContentOffset(CGPoint(x: 0, y: self.infoTableView.contentOffset.y), animated: false) } if scrollView == self.contentView { let x = self.contentView.contentOffset.x if x < 0 { self.contentView.contentOffset.x = 0 } } } } extension LQQuoteDetailCategoryController : JXCategoryListContentViewDelegate { func listView() -> UIView! { return self.view } }
import Foundation class LQQuotedDetailModel { var variety : String? //品种 var currentPrice : Float? //当前价 var upAndDownPrice : Float? //涨跌 var scope : Float? //幅度 var buyPrice : Float?//买价 var salePrice : Float? //卖价 var yesterdayHarvest : Float? //昨收 var turnover : Float? //成交量 var topPrice : Float? //最高价 var openingPrice : Float? //开盘价 var bottomPrice : Float? //最低价 init(variety: String,currentPrice:Float,upAndDownPrice:Float,scope:Float,buyPrice:Float,salePrice:Float,yesterdayHarvest:Float,topPrice:Float,openingPrice:Float,bottomPrice:Float,turnover:Float) { self.variety = variety self.currentPrice = currentPrice self.upAndDownPrice = upAndDownPrice self.scope = scope self.buyPrice = buyPrice self.salePrice = salePrice self.yesterdayHarvest = yesterdayHarvest self.topPrice = topPrice self.openingPrice = openingPrice self.bottomPrice = bottomPrice self.turnover = turnover } }
本文只写Demo,正式使用时,自己结合Api做调整。
第一列固定,其余列可横向滚动查看。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 百万级群聊的设计实践
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
2020-04-23 【iOS】判断字符串是否是url及从字符串中提取url