ios - 如何更改 UITableViewCell 的高度?

标签 ios uitableview

我已经在单元格内实现了一个带有 ScrollView 的表格 View 。该单元格由两个 View 组成,第二个 View (以绿色显示)在滑动后出现:

picture

我现在想要实现的是,当单元格向右滑动时,单元格高度逐渐扩大。因此,当我开始向右滑动单元格并且绿色 subview 在主屏幕上变得可见时,我希望单元格增加高度直到绿色 subview 完全可见。然后当我向左滑动时,一切都恢复正常。

由于 UITableViewCell 符合 ScrollView 委托(delegate),我怀疑我在我的单元格子类中编写了一些代码 - 也许使用 ScrollView 的 contentOffset.y 来使用 scrollViewDidScroll。

最佳答案

这是一个使用自动布局和自动调整单元格大小的示例 (Swift 3)。不确定您打算如何“开始”绿色 View ,因此此演示将其初始化为 40 磅宽(高度包含在宽度的 50% 内)。

您可以简单地创建一个新的 .swift 文件并将其粘贴进去,然后在 Storyboard 中添加一个 UITableViewController 并将其类分配给 StretchCellTableViewController。其他一切都是在代码中创建的……不需要 IBOutlets。

//
//  StretchCellTableViewController.swift
//  SWTemp2
//
//  Created by Don Mag on 6/22/17.
//  Copyright © 2017 DonMag. All rights reserved.
//

import UIKit

class NonStretchCell: UITableViewCell {

    // pretty standard one-label cell

    var theLabel: UILabel!

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupCell()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupCell()
    }

    func setupCell() {

        theLabel = UILabel()
        theLabel.font = UIFont.systemFont(ofSize: 16.0, weight: UIFontWeightLight)
        theLabel.numberOfLines = 0
        theLabel.translatesAutoresizingMaskIntoConstraints = false

        self.addSubview(theLabel)

        theLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 8.0).isActive = true
        theLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 6.0).isActive = true
        theLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -6.0).isActive = true
        theLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -8.0).isActive = true

    }

}

class StretchCell: UITableViewCell {

    var stretchView: UIView!

    var widthConstraint: NSLayoutConstraint!

    var scaleAction : ((CGFloat)->())?

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupCell()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupCell()
    }

    func setBarWidth(_ w: CGFloat) -> Void {
        widthConstraint.constant = w
    }

    func setupCell() {

        // instantiate the view
        stretchView = UIView()
        stretchView.translatesAutoresizingMaskIntoConstraints = false
        stretchView.backgroundColor = .green

        // add it to self (the cell)
        self.addSubview(stretchView)

        // "pin" it to top, bottom and left
        stretchView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0.0).isActive = true
        stretchView.topAnchor.constraint(equalTo: self.topAnchor, constant: 0.0).isActive = true
        stretchView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0.0).isActive = true

        // set height constraint to be 50% of the width
        stretchView.heightAnchor.constraint(equalTo: stretchView.widthAnchor, multiplier: 0.5).isActive = true

        // instantiate the width constraint
        widthConstraint = NSLayoutConstraint(item: stretchView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 40)

        // needs priority of 999 so auto-layout doesn't complain
        widthConstraint.priority = 999

        // activate the width constraint
        NSLayoutConstraint.activate([widthConstraint])

        // create a UIPanGestureRecognizer and add it to the stretch view
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(didPan(sender:)))

        stretchView.addGestureRecognizer(panGesture)

    }

    func didPan(sender: UIPanGestureRecognizer) {

        let loc = sender.location(in: self)

        if sender.state == .began {

            // if you want to do something on drag start...
            //print("Gesture began")

        } else if sender.state == .changed {

            //print("Gesture is changing", loc)

            // update the width of the stretch view (but keep it at least 20-pts wide, so it doesn't disappear)
            // height is set to 1:1 so it updates automatically
            widthConstraint.constant = max(loc.x, 20)

            // call back to the view controller
            scaleAction?(widthConstraint.constant)

        } else if sender.state == .ended {

            // if you want to do something on drag end...
            //print("Gesture ended")

        }

    }

}


class StretchCellTableViewController: UITableViewController {

    // array to track the bar widths, assuming we have more than one row with a bar
    // only a few rows will have the "stretch bar" - but for this example we'll just track a barWidth for *every* row
    var barWidths = [CGFloat]()

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 80

        tableView.register(StretchCell.self, forCellReuseIdentifier: "StretchCell")
        tableView.register(NonStretchCell.self, forCellReuseIdentifier: "NonStretchCell")

        // init array for barWidths... initial value: 40, 30 slots
        barWidths = Array(repeating: 40, count: 30)
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return barWidths.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        // just make every 5th row a "Stretch" cell (starting at #3)
        if indexPath.row % 5 == 3 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "StretchCell", for: indexPath) as! StretchCell
            cell.selectionStyle = .none

            // cells are reused, so set the bar width to our saved value
            cell.setBarWidth(barWidths[indexPath.row])

            // "call-back" function
            cell.scaleAction = {
                (newWidth) in
                // update the bar width in our tracking array
                self.barWidths[indexPath.row] = newWidth

                // disable Animations, because we're changing the size repeatedly
                UIView.setAnimationsEnabled(false)

                // wrap begin/end updates() to force row-height re-calc
                self.tableView.beginUpdates()
                self.tableView.endUpdates()

                // re-enable Animations
                UIView.setAnimationsEnabled(true)
            }

            cell.preservesSuperviewLayoutMargins = false
            cell.separatorInset = UIEdgeInsets.zero
            cell.layoutMargins = UIEdgeInsets.zero

            return cell
        }

        let cell = tableView.dequeueReusableCell(withIdentifier: "NonStretchCell", for: indexPath) as! NonStretchCell

        // just for demonstration's sake

        if indexPath.row % 7 == 5 {
            cell.theLabel.text = "Row: \(indexPath.row) - This is just to show the text wrapping onto multiple lines. Pretty standard for auto-sizing UITableView cells."
        } else {
            cell.theLabel.text = "Row: \(indexPath.row)"
        }

        cell.preservesSuperviewLayoutMargins = false
        cell.separatorInset = UIEdgeInsets.zero
        cell.layoutMargins = UIEdgeInsets.zero

        return cell
    }

}

结果是:

enter image description here

关于ios - 如何更改 UITableViewCell 的高度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44683312/

相关文章:

ios - 发布到 AppStore 时配置文件显示错误的应用程序名称

ios - 如何删除表格 View 单元格之间的黑线?

ios - UITableViewCell 的两个标签

ios - 在 UISearchBar 中按 "x"时关闭键盘

ios - 更改不同iOS版本的UITableViewStyle

iphone - UITableView 中的默认 list

ios - 将自定义 UITableViewCell 内容与标题对齐

ios - 如何让 iOS 在 tableView 上显示删除按钮,但不允许从右侧完全滑动以删除

android - 在手机(ios android)跨平台QT上调用sqlite数据库路径

ios - 将 NSArray 传递给函数的 Objective-C 错误