实现两个UITableView垂直同步滑动,右边列表水平滑动,左边固定

两个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 的列重用。如有其他更好的方案欢迎留言交流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追夢秋陽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值