swift 如何制作可扩展的UITableView头文件?

ibps3vxo  于 2023-01-25  发布在  Swift
关注(0)|答案(2)|浏览(126)

我想先显示一半的页眉。当用户点击页眉中的一个按钮时,页眉的其余部分会向下滑动并显示出来。当用户再次点击按钮时,页眉会向上滑动回到原始大小(1/2大小)。
然而,当我试图扩展标题的高度时,它覆盖了tableView单元格,而不是将它们向下推。

func prepareHeader(){
    let headerHeight = CGFloat(51.0)
    headerView = UIView(frame: CGRect(x: 0, y: 0, width: screenWidth, height: headerHeight))
    headerView.backgroundColor = UIColor.whiteColor()
    headerView.layer.addSublayer(bottomBorder)
    headerView.layer.masksToBounds = true

    let toggler = UIButton(type: .Custom)
    toggler.frame = CGRectMake(0, 0, 40, 40)
    toggler.backgroundColor = FlatGreen()
    toggler.addTarget(self, action: "toggleHeader:", forControlEvents: UIControlEvents.TouchUpInside)
    headerView.addSubview(toggler)

    self.tableView.tableHeaderView = headerView

}

func toggleHeader(sender: UIButton){
    print("Pushed")
    var newFrame = self.headerView.frame
    newFrame.size.height = CGFloat(100)
    self.headerView.frame = newFrame
}
tp5buhyn

tp5buhyn1#

我们想要的

可以动态打开和关闭的表格视图标题。

溶液1:无接口构建器

class ViewController: UIViewController {

    var headerView = UIView()
    var tableView  = UITableView()
    var isHeaderOpen = false
    let HEADER_CLOSED_HEIGHT: CGFloat = 100
    let HEADER_OPEN_HEIGHT: CGFloat = 200

    var headerClosedHeightConstraint: NSLayoutConstraint!
    var headerOpenHeightConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Add the table view to the screen.
        view.addSubview(tableView)

        // Make the table view fill the screen.
        tableView.translatesAutoresizingMaskIntoConstraints = false
        view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[tableView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["tableView": tableView]))
        view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[tableView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["tableView": tableView]))

        // Add the header view to the table view.
        tableView.tableHeaderView = headerView
        headerView.backgroundColor = UIColor.redColor()
        headerView.translatesAutoresizingMaskIntoConstraints = false

        // Add a button to the header.
        let button = UIButton(type: .Custom)
        button.setTitle("Toggle", forState: .Normal)
        headerView.addSubview(button)
        button.translatesAutoresizingMaskIntoConstraints = false
        headerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[button]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["button": button]))
        headerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[button]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["button": button]))
        button.addTarget(self, action: "toggleHeaderAction:", forControlEvents: .TouchUpInside)

        // Make the header full width.
        view.addConstraint(NSLayoutConstraint(item: headerView, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 1, constant: 0))

        // Create the constraints for the two different header heights.
        headerClosedHeightConstraint = NSLayoutConstraint(item: headerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 0, constant: HEADER_CLOSED_HEIGHT)

        // Create the height constraint for the header's other height for later use.
        headerOpenHeightConstraint = NSLayoutConstraint(item: headerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: HEADER_OPEN_HEIGHT)

        closeHeader()   // Close header by default.
    }

    func openHeader() {
        headerView.removeConstraint(headerClosedHeightConstraint)
        headerView.addConstraint(headerOpenHeightConstraint)
        updateHeaderSize()
        isHeaderOpen = true
    }

    func closeHeader() {
        headerView.removeConstraint(headerOpenHeightConstraint)
        headerView.addConstraint(headerClosedHeightConstraint)
        updateHeaderSize()
        isHeaderOpen = false
    }

    func updateHeaderSize() {
        // Calculate the header's new size based on its new constraints and set its frame accordingly.
        let size = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
        var frame = headerView.frame
        frame.size.height = size.height
        headerView.frame = frame
        tableView.tableHeaderView = headerView
        self.headerView.layoutIfNeeded()
    }

    func toggleHeader() {
        if isHeaderOpen {
            closeHeader()
        } else {
            openHeader()
        }
    }

    func toggleHeaderAction(sender: AnyObject) {
        toggleHeader()
    }
}

溶液2:使用界面生成器

要使UITableView标题动态更改高度,请尝试以下操作。
在你的故事板中,首先添加一个UITableView到你的视图控制器中,然后添加一个UIView作为UITableView的第一个子视图(Interface Builder自动将其解释为UITableView的标题视图)。

在表和表头上连接一个插座,这样我们就可以在后面的代码中访问它们。

@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var headerView: UIView!

接下来,我们在代码中创建两个约束(打开和关闭),稍后我们将添加/删除这两个约束以切换页眉的高度。

var headerOpenHeightConstraint: NSLayoutConstraint!
var headerClosedHeightConstraint: NSLayoutConstraint!

让我们创建一个标记来跟踪头部的打开/关闭状态,并且指定打开的头部高度。

var isHeaderOpen = false
let HEADER_OPEN_HEIGHT: CGFloat = 200

Interface Builder会自动将我们创建的标题的尺寸转换为自动布局约束。由于我们要自己更改标题的高度,因此需要添加我们自己的替换约束并删除这些自动约束(NSAutoresizingMaskLayoutConstraints)。在viewDidLoad()中,添加以下内容(将默认标题高度作为闭合高度,HEADER_OPEN_HEIGHT作为开放标题高度)。

override func viewDidLoad() {
    super.viewDidLoad()

    // The header needs a new width constraint since it will no longer have the automatically generated width.
    view.addConstraint(NSLayoutConstraint(item: headerView, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 1, constant: 0))

    // Add the height constraint for the default state (closed header).
    headerClosedHeightConstraint = NSLayoutConstraint(item: headerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: headerView.bounds.height)
    headerView.addConstraint(headerClosedHeightConstraint)

    // Make the constraint we'll use later to open the header.
    headerOpenHeightConstraint = NSLayoutConstraint(item: headerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: HEADER_OPEN_HEIGHT)

    // Finally we disable this so that we don't get Interface Builder's automatically generated constraints
    // messing with our constraints.
    headerView.translatesAutoresizingMaskIntoConstraints = false
}

最后,在Interface Builder中添加一个按钮,并将其连接到视图控制器中的一个操作。

@IBAction func toggleHeaderAction(sender: AnyObject) {

    // Add/remove the appropriate constraints to toggle the header.
    if isHeaderOpen {
        headerView.removeConstraint(headerOpenHeightConstraint)
        headerView.addConstraint(headerClosedHeightConstraint)
    } else {
        headerView.removeConstraint(headerClosedHeightConstraint)
        headerView.addConstraint(headerOpenHeightConstraint)
    }

    // Calculate the header's new size based on its new constraints.
    let size = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

    // Give the header its new height.
    var frame = headerView.frame
    frame.size.height = size.height
    headerView.frame = frame
    headerView.setNeedsLayout()
    headerView.layoutIfNeeded()
    tableView.tableHeaderView = headerView

    isHeaderOpen = !isHeaderOpen
}
omhiaaxx

omhiaaxx2#

有几个想法可以尝试

  • 设置好之后,立即调用self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition .Top:, animated: true),其中indexPath是之前位于顶部的单元格,您可以尝试是否将其设置为动画
  • 从你的描述中,我无法判断你是否对新框架的内容大小偏移有问题(也就是单元格实际上在下面,你不能向上滚动到它们)。如果是这样,再次设置self.tableView.headerView会改善这种情况吗?

相关问题