Swift - 如何使用 XIB 文件创建自定义 viewForHeaderInSection?

2024-02-27

我可以像下面这样以编程方式创建简单的自定义 viewForHeaderInSection。但我想做更复杂的事情,可能与不同的类连接并像 tableView 单元格一样访问它们的属性。很简单,我想看看我在做什么。

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    if(section == 0) {

        let view = UIView() // The width will be the same as the cell, and the height should be set in tableView:heightForRowAtIndexPath:
        let label = UILabel()
        let button   = UIButton(type: UIButtonType.System)

        label.text="My Details"
        button.setTitle("Test Title", forState: .Normal)
        // button.addTarget(self, action: Selector("visibleRow:"), forControlEvents:.TouchUpInside)

        view.addSubview(label)
        view.addSubview(button)

        label.translatesAutoresizingMaskIntoConstraints = false
        button.translatesAutoresizingMaskIntoConstraints = false

        let views = ["label": label, "button": button, "view": view]

        let horizontallayoutContraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[label]-60-[button]-10-|", options: .AlignAllCenterY, metrics: nil, views: views)
        view.addConstraints(horizontallayoutContraints)

        let verticalLayoutContraint = NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: 0)
        view.addConstraint(verticalLayoutContraint)

        return view
    }

    return nil
}


func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 50
}

有没有人解释一下如何使用 xib 创建自定义 tableView 标题视图?我遇到过旧的 Obj-C 主题,但我对 Swift 语言很陌生。如果有人解释得这么详细,那就太好了。

1.issue:按钮 @IBAction 未与我的 ViewController 连接。(Fixed)

使用文件所有者、ViewController 基类解决(单击左侧大纲菜单。)

2.issue:表头高度问题(Fixed)

解决添加headerView.clipsToBounds = true in viewForHeaderInSection: 方法。

对于约束警告 这个答案解决了我的问题 https://stackoverflow.com/questions/11664115/unable-to-simultaneously-satisfy-constraints-will-attempt-to-recover-by-breakin/30096600#30096600:

当我在 viewController 中使用此方法添加 ImageView 甚至相同的高度约束时,它会流过 tableView 行看起来像图片 https://i.stack.imgur.com/yoYQ6.png.

 func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 120
}

如果我使用viewDidLoad中的automaticallyAdjustsScrollViewInsets,在这种情况下图像会在navigationBar下流动。 -固定的-

self.automaticallyAdjustsScrollViewInsets = false

3.issue:“查看”下的“如果”按钮(Fixed)

@IBAction func didTapButton(sender: AnyObject) {
    print("tapped")

    if let upView = sender.superview {
        if let headerView = upView?.superview as? CustomHeader {
            print("in section \(headerView.sectionNumber)")
        }

    }
}

基于 NIB 的标头的典型过程是:

  1. Create UITableViewHeaderFooterView子类至少有一个标签的出口。您可能还想给它一些标识符,您可以通过该标识符对该标头对应的部分进行逆向工程。同样,您可能想要指定一个协议,标头可以通过该协议向视图控制器通知事件(例如点击按钮)。因此,在 Swift 3 及更高版本中:

    // if you want your header to be able to inform view controller of key events, create protocol
    
    protocol CustomHeaderDelegate: class {
        func customHeader(_ customHeader: CustomHeader, didTapButtonInSection section: Int)
    }
    
    // define CustomHeader class with necessary `delegate`, `@IBOutlet` and `@IBAction`:
    
    class CustomHeader: UITableViewHeaderFooterView {
        static let reuseIdentifier = "CustomHeader"
    
        weak var delegate: CustomHeaderDelegate?
    
        @IBOutlet weak var customLabel: UILabel!
    
        var sectionNumber: Int!  // you don't have to do this, but it can be useful to have reference back to the section number so that when you tap on a button, you know which section you came from; obviously this is problematic if you insert/delete sections after the table is loaded; always reload in that case
    
        @IBAction func didTapButton(_ sender: AnyObject) {
            delegate?.customHeader(self, didTapButtonInSection: section)
        }
    
    }
    
  2. 创建NIB。就我个人而言,我给 NIB 赋予与基类相同的名称,以简化项目中文件的管理并避免混淆。无论如何,关键步骤包括:

    • 创建视图 NIB,或者如果您从空 NIB 开始,请将视图添加到 NIB;

    • 将视图的基类设置为您的任何内容UITableViewHeaderFooterView子类是(在我的例子中,CustomHeader);

    • 在 IB 中添加您的控制和约束;

    • Hook up @IBOutletSwift 代码中对出口的引用;

    • 将按钮连接到@IBAction; and

    • 对于 NIB 中的根视图,请确保将背景颜色设置为“默认”,否则您会收到有关更改背景颜色的烦人警告。

  3. In the viewDidLoad在视图控制器中,注册 NIB。在 Swift 3 及更高版本中:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        tableView.register(UINib(nibName: "CustomHeader", bundle: nil), forHeaderFooterViewReuseIdentifier: CustomHeader.reuseIdentifier)
    }
    
  4. In viewForHeaderInSection,使用您在上一步中指定的相同标识符使可重用视图出队。完成此操作后,您现在可以使用您的插座,您不必对以编程方式创建的约束等执行任何操作。您唯一需要做的事情(为了使按钮工作的协议)是指定其委托。例如,在 Swift 3 中:

    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "CustomHeader") as! CustomHeader
    
        headerView.customLabel.text = content[section].name  // set this however is appropriate for your app's model
        headerView.sectionNumber = section
        headerView.delegate = self
    
        return headerView
    }
    
    override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 44  // or whatever
    }
    
  5. 显然,如果您要将视图控制器指定为delegate对于标题视图中的按钮,您必须遵守该协议:

    extension ViewController: CustomHeaderDelegate {
        func customHeader(_ customHeader: CustomHeader, didTapButtonInSection section: Int) {
            print("did tap button", section)
        }
    }
    

当我列出所有涉及的步骤时,这一切听起来很令人困惑,但是一旦您完成了一两次,它实际上非常简单。我认为这比以编程方式构建标题视图更简单。


In 马特的回答 https://stackoverflow.com/a/50087040/1271826,他抗议道:

问题很简单,就是你无法神奇地转动一个UIView在笔尖中进入UITableViewHeaderFooterView只需在身份检查器中声明即可。

这是不正确的。如果使用上面基于NIB的方法,则为此头视图的根视图实例化的类is a UITableViewHeaderFooterView子类,不是UIView。它实例化您为 NIB 根视图的基类指定的任何类。

然而,正确的是这个类的一些属性(特别是contentView https://developer.apple.com/documentation/uikit/uitableviewheaderfooterview/1624914-contentview) 不用于这种基于 NIB 的方法。它确实应该是可选属性,就像textLabel https://developer.apple.com/documentation/uikit/uitableviewheaderfooterview/1624912-textlabel and detailTextLabel https://developer.apple.com/documentation/uikit/uitableviewheaderfooterview/1624910-detailtextlabel是(或者更好的是,他们应该添加适当的支持UITableViewHeaderFooterView在IB中)。我同意苹果公司的这一设计很糟糕,但在我看来,这是一个草率、特殊的细节,但考虑到表格视图中的所有问题,这只是一个小问题。例如,值得注意的是,这么多年过去了,我们仍然无法在故事板中实现原型页眉/页脚视图,而必须完全依赖这些 NIB 和类注册技术。

但是,得出不能使用的结论是错误的register(_:forHeaderFooterViewReuseIdentifier:) https://developer.apple.com/documentation/uikit/uitableview/1614921-register,这是一个自 iOS 6 以来一直在积极使用的 API 方法。我们不要把孩子和洗澡水一起倒掉。


See 之前的修订版 https://stackoverflow.com/revisions/36931047/3Swift 2 演绎版的答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Swift - 如何使用 XIB 文件创建自定义 viewForHeaderInSection? 的相关文章

随机推荐

  • 正确的 XPath 查询以获取 div 内部文本

    我正在使用 XPath 查询 HTML 文档 其中以下 div 包含文本 div class h1 2008 Honda Accord Coupe div
  • 如何实现标记嵌入的中心损失和其他运行平均值

    最近的一篇论文 here http ydwen github io papers WenECCV16 pdf 引入了一种称为中心损失的二次损失函数 它基于批次中嵌入之间的距离以及每个相应类的运行平均嵌入 TF Google 群组中有一些讨论
  • OpenGL 或 OpenGL ES [重复]

    这个问题在这里已经有答案了 我应该学什么 OpenGL 4 1 还是 OpenGL ES 2 0 我将使用 Qt 开发桌面应用程序 但几个月后我也可能开始开发移动应用程序 我对 3D 3D 数学等一无所知 我宁愿花 100 美元买一本好书
  • Clojure + Clojurescript:读取当前文件代码的宏

    我已经尝试过的 defmacro magic slurp file 这在 clojure 中工作得很好 但在 clojurescript 中则不然 至少在 lein Figwheel 中不行 原始问题 我需要以下内容才能在 Clojure
  • 如何从列表列表中制作平面列表?

    我有一个列表 例如 1 2 3 4 5 6 7 8 9 我怎样才能把它压平以获得 1 2 3 4 5 6 7 8 9 If your list of lists comes from a nested list comprehension
  • 替换 R 中的单反斜杠

    我已经在堆栈溢出中阅读了有关此主题的一些问题和答案 但仍然不知道如何解决此问题 我的目的是将Windows资源管理器中的文件目录字符串转换为R中可识别的形式 例如C Users Public 需要转换为 C Users Public 基本上
  • 同一应用程序在单个设备上的开发和生产版本

    请建议如何解决需要在一台设备上安装两次同一应用程序的问题 需要一个用于开发 一个在生产中用于测试和使用 这样做的简单方法是什么 我尝试手动更改包名称 但这会导致合并时出现痛苦 如果您使用 ADT v 20 您可以轻松更改包名称 只需右键单击
  • 测试 FormArray

    我有一个PhoneNumbersFormComponent其模板如下所示 div div div div
  • 如何编写更新查询来减去某个值?

    在 sql 查询中准备语句的情况下 这是执行减法运算的正确方法吗 sql UPDATE users set credits credits price WHERE username 根据 price 的值减去用户积分的代码 price ro
  • Rmarkdown/knitr subfigure 不同的图形尺寸

    我试图在 Rmarkdown 中实现子图的不同高度和宽度 我希望只是提供fig height and fig width每个向量都可以工作 因为这似乎确实适用于out height and out width title Untitled
  • 从自定义属性修饰的属性中获取价值?

    我编写了一个自定义属性 用于类的某些成员 public class Dummy MyAttribute public string Foo get set MyAttribute public int Bar get set 我可以从类型中
  • Java Swing - 从另一种方法设置 Jlabel 文本

    我对 Java 和 Swing 还很陌生 我正在使用 Windowbuilder 来尝试我的一些 GUI 想法 但在尝试设置 Jlabel 的文本时遇到了问题 Windowbuilder 在initialize 方法中自动创建了一个名为pa
  • Java 构造函数链接 [重复]

    这个问题在这里已经有答案了 你好 我刚刚学习 Java 中的构造函数链 并且有一些问题 首先 有人可以解释一下我什么时候需要使用这个吗 我真的无法想象出一种情况 在此示例中 在没有参数的构造函数中 我调用另一个构造函数 我如何访问这个新的
  • bitbucket 剥离了 git 修订

    推送到 bitbucket 后 我 的同事提交被删除 并且 bitbucket 新闻源上出现一条消息 stripped 6f9de58aa748 from projektA 4 hours ago stripped 54dae89de600
  • Android 本机代码如何针对多种处理器类型?

    据我了解 Android 上的本机代码是直接与特定设备的处理器一起工作的代码 因此 如果我想利用某个处理器 我会使用本机代码 但是 如果我想制作一个包含本机代码但面向多个处理器的应用程序 会发生什么情况 我是否必须制作多个应用程序 每个架构
  • 如何将图像重置到原始位置

    我正在使用 TouchImageView 类 位于https github com MikeOrtiz TouchImageView https github com MikeOrtiz TouchImageView 我使用这个类对我的图像
  • 指定的容器不存在

    我陷入了这个错误The specified container does not exist 让我解释 CloudBlobClient blobStorage GetBlobStorage upload CloudBlockBlob blo
  • 如何隐藏RCP中的默认菜单?

    我是 Eclipse RCP 插件开发的新手 我用自己的视角编写了一个插件 并在其中添加了视角特定的菜单 我的问题是如何隐藏 Eclipse 中提供的默认菜单 例如 编辑 导航 搜索 项目 我尝试使用 并提出我的观点具体条件 以及菜单贡献
  • 未搜索SBT maven本地存储库

    我想从本地 Maven 存储库加载一些库 我已经配置了 sbt 0 13 plugins plugins sbt resolvers Resolver sonatypeRepo snapshots resolvers Resolver ma
  • Swift - 如何使用 XIB 文件创建自定义 viewForHeaderInSection?

    我可以像下面这样以编程方式创建简单的自定义 viewForHeaderInSection 但我想做更复杂的事情 可能与不同的类连接并像 tableView 单元格一样访问它们的属性 很简单 我想看看我在做什么 func tableView