【问题标题】:headers are removed when expanding a section in a UITableView展开 UITableView 中的部分时,标题被删除
【发布时间】:2020-08-08 08:26:31
【问题描述】:

我对 Swift 和 IOS 编程非常陌生,但我正在尝试创建一个应用程序。我想要一个 UITableView ,其中有一些标题,如果您单击它们,它们将打开或关闭,具体取决于它们是否打开。是否可以使用标题执行此操作,还是需要使用普通单元格?到目前为止,这就是我设置所有内容的方式。感谢您的帮助?

编辑:

我现在可以打开和关闭部分,但有些部分会被删除。 我已经用迄今为止所做的编辑更新了代码。

她是我点击某物时的样子。

var settings: [settingOptions] = [
    settingOptions(isOpened: true, setting: "appearance", options: ["light mode", "dark mode"]),
    settingOptions(isOpened: true, setting: "unit system", options: ["liters & milli liters", "ounzes"]),
    settingOptions(isOpened: true, setting: "change goal", options: ["goal"]),
    settingOptions(isOpened: true, setting: "how to use", options: []),
    settingOptions(isOpened: true, setting: "remove data", options: [])]
@objc func expandOrCollapsSection(_ sender: UIGestureRecognizer){
    print("Do something with section")
    guard let section = sender.view?.tag else { return }
    var indexPaths = [IndexPath]()
    for row in settings[section].options.indices {
        let indexPath = IndexPath(row: row, section: section)
        indexPaths.append(indexPath)
    }

    let ioOpend = settings[section].isOpened
    settings[section].isOpened = !ioOpend
    if ioOpend {
        tableView.deleteRows(at: indexPaths, with: .none)
    } else {
        tableView.insertRows(at: indexPaths, with: .none)
    }
}



extension AboutVC: UITableViewDelegate, UITableViewDataSource{

     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "header") as! SettingOptionCell
        cell.setting = settings[indexPath.section].options[indexPath.row]

        return cell
    }

     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return settings[section].isOpened ? settings[section].options.count : 0
    }

     func numberOfSections(in tableView: UITableView) -> Int {
        return settings.count
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
         let cell = tableView.dequeueReusableCell(withIdentifier: "settingCell") as! SettingsCell
        cell.setting = settings[section]
        cell.selectionStyle = .none
        cell.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(expandOrCollapsSection)))
        cell.tag = section
        return cell
    }
     func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
         return 60
    }


    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    }

    }
}

class SettingOptionCell: UITableViewCell {
    var setting: String? {
        didSet {
            guard let string    = setting else {return}
            option.text         = string.capitalized
        }
    }
    let option: UILabel = {
        let lable           = UILabel()
        lable.text          = "test"
        lable.textColor     = UIColor.white
        lable.font          = UIFont(name: "AmericanTypewriter", size: 17)
        lable.translatesAutoresizingMaskIntoConstraints = false
        return lable
        }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.addSubview(option)
        option.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 20).isActive = true
        option.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
        self.backgroundColor = .none
    }



    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class SettingsCell: UITableViewCell {
    var setting: settingOptions? {
        didSet {
            guard let setting = setting else {return}
            self.title.text = setting.setting.uppercased()
        }
    }
    var title: UILabel = {
        let lable       = UILabel()
        lable.text      = "Test"
        lable.font      = UIFont(name: "AmericanTypewriter", size: 20)
        lable.textColor = .white
        lable.translatesAutoresizingMaskIntoConstraints = false
        return lable
    }()
    var container: UIView = {
        let view                                        = UIView()
        view.clipsToBounds                              = true
        view.backgroundColor                            = .none
        view.translatesAutoresizingMaskIntoConstraints  = false
        return view
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.backgroundColor                = .none
        self.isUserInteractionEnabled       = true
        contentView.addSubview(container)
        container.addSubview(title)
        title.leftAnchor.constraint(equalTo: container.leftAnchor).isActive                     = true
        title.centerYAnchor.constraint(equalTo: container.topAnchor,constant: 30).isActive      = true

        container.topAnchor.constraint(equalTo:contentView.topAnchor).isActive                  = true
        container.leftAnchor.constraint(equalTo:contentView.leftAnchor).isActive                = true
        container.rightAnchor.constraint(equalTo:contentView.rightAnchor).isActive              = true
        container.bottomAnchor.constraint(equalTo:contentView.bottomAnchor).isActive            = true
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

【问题讨论】:

    标签: ios swift uitableview user-interface


    【解决方案1】:

    是的,它可以使用标题, 为所有标题视图添加tag 和UITapGestureRecogniser

    在设置数据结构中添加isExpanded布尔键

    给你,写个手势动作方法

    @objc func handleTapGesture(_ sender:UIGestureRecogniser) {
                  let gesture = UIGestureRecognizer.init()
        guard let section = gesture.view?.tag else { return }
        let indexPaths = [IndexPath]()
        for row in settings[section].options.indices {
            let indexpath = IndexPath.init(row: row, section: section)
        }
        // revising the value....
        let isExpanded = settings[section].isExpanded
        settings[section].isExpanded = !isExpanded
        if isExpanded {
             tableView.deleteRows(at: indexPaths, with: .fade)
        } else {
             tableView.insertRows(at: indexPaths, with: .fade)
        }
    }
    

    行数小修改

     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    
        return settings[section].isExpanded ? settings[section].options.count : 0
    }
    

    我推荐下面的视频。 https://www.youtube.com/watch?v=Q8k9E1gQ_qg

    【讨论】:

    • 这不起作用,但在对您的代码进行一些修改后,它将打开和关闭一个部分,但它会删除一些标题。她是我所做的修改:guard let section = sender.view?.tag else { return } var indexPaths = [IndexPath]() for row in settings[section].options.indices { let indexPath = IndexPath(row: row,部分:部分)indexPaths.append(indexPath)打印(indexPath)}
    • 我已经更新了代码并添加了所发生情况的图像
    • @PetterBraka。首先那太好了,你找到了错过的那条线,我忘了添加那条线。我不建议将单元格重用于标题视图。我认为这是删除标题问题的原因。参考:stackoverflow.com/a/960157/8879068
    • 谢谢。是的,当我改为使用自定义标题时,它工作得很好。 @sreekanth-m
    【解决方案2】:

    定义变量以存储您的表格视图部分状态

    var isCollapsed:Bool = true
    

    然后您可以将 UITapGestureRecognizer 添加到您的表格视图标题视图中

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
            let cell = tableView.dequeueReusableCell(withIdentifier: "settingCell") as! SettingsCell
            cell.setting = settings[section]
            cell.selectionStyle = .none
            cell.isUserInteractionEnabled = true
            cell.tag = section
            cell.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didMenuItemClicked(_:))))
            return cell
    }
    

    下一步,您要根据 isCollapsed 状态配置表格视图单元格的行为

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            if !isCollapsed {
                let cell = tableView.dequeueReusableCell(withIdentifier: "header") as! SettingOptionCell
                cell.setting = settings[indexPath.section].options[indexPath.row]
                return cell
            }else{
                let cell = UITableViewCell()
                cell.translatesAutoresizingMaskIntoConstraints = false
                cell.heightAnchor.constraint(equalToConstant: 0).isActive = true
                cell.widthAnchor.constraint(equalToConstant: 0).isActive = true
                return cell
            }
    
    }
    

    现在你可以编写函数来显示、隐藏子项目,

    @objc func didMenuItemClicked(_ sender : UITapGestureRecognizer){
    
            isCollapsed = !isCollapsed
            myTable.reloadSections([sender.view!.tag], with: .fade)
    }
    

    【讨论】:

    • 当我这样做时,所有标题在我单击标题后都会丢失,但它会显示该部分的单元格。
    • 我已经更新了代码并添加了所发生情况的图像
    【解决方案3】:

    为了解决标题消失的问题,我将用作标题的单元格类型更改为 UITableViewHeaderFooterView。

    class SettingsCell: UITableViewHeaderFooterView {
    //init()
    }
    

    像这样注册:

    tableView.register(SettingsCell.self, forHeaderFooterViewReuseIdentifier: "header")
    

    像这样出队:

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let cell = tableView.dequeueReusableHeaderFooterView(withIdentifier: "header") as! SettingsCell
        cell.setting = settings[section]
        cell.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(expandOrCollapsSection)))
        cell.tag = section
        return cell
    }
    

    为了修复该部分的打开和关闭问题,我实施了 sreekanth 的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-27
      • 1970-01-01
      • 2017-07-06
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多