簡體   English   中英

如何在持有時逐漸增加tableview單元格的大小

[英]How to increase the size of the tableview cell gradually upon holding it

我想要做的(逐字逐句):在指定的時間內保留一個 tableview 單元格。 一旦達到該時間段,細胞高度就會逐漸增加。 當我松開手指時,細胞高度停止增長。

我有什么:我有幾個 tableViewCells。 按下單元格指定時間后,使用:

let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: Selector("longPress:"))
longPressRecognizer.minimumPressDuration = 1.0s
longPressRecognizer.delegate = self
self.view.addGestureRecognizer(longPressRecognizer)

我想增加單元格高度。 但是如果不知道觸摸位於哪一行,我就無法做到這一點,所以我走到了這里:

func longPress(longPressGestureRecognizer: UILongPressGestureRecognizer) {
    if longPressGestureRecognizer.state == UIGestureRecognizerState.began {
        let touchPoint = longPressGestureRecognizer.location(in: self.tableView)
        if let indexPath = tableView.indexPathForRow(at: touchPoint) {
            //let cell = tableView.cellForRow(at: indexPath)
        }
    }
}

我想控制 rowHeight,但這僅在 tableView 函數中,所以我不知道如何調用它。

我不確定如何繼續。 我不是在尋找與 .beginUpdates 和 .endUpdates 相關的任何東西,因為我希望細胞生長是漸進的,最好是動畫的。

任何幫助將不勝感激,因為我一直在尋找這個特定問題的答案很長一段時間。

包含 rowHeight 聲明的代碼:

     override func viewDidLoad() {
            super.viewDidLoad()

    //        let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: Selector("longPress:"))
    //        longPressRecognizer.minimumPressDuration = 1.0 // 1 second press
    //        longPressRecognizer.delegate = self
    //        self.view.addGestureRecognizer(longPressRecognizer)

            tableView.delegate = self
            tableView.dataSource = self
            tableView.allowsSelection = false

            self.tableView.reorder.delegate = self

            view.backgroundColor = UIColor(red:0.64, green:0.93, blue:0.78, alpha:1.0)
            tableView.backgroundColor = UIColor.clear

            tableView.rowHeight = 84
            tableView.rowHeight = UITableViewAutomaticDimension


            // Do any additional setup after loading the view.
        }

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 100
    }
Declare property for height of the cell and return this property in the tableviews's delegate method heightForRowAtIndexPath method

var heightForCell = 100

func longPress(longPressGestureRecognizer: UILongPressGestureRecognizer) {
if longPressGestureRecognizer.state == UIGestureRecognizerState.began {
    let touchPoint = longPressGestureRecognizer.location(in: self.tableView)
    if let indexPath = tableView.indexPathForRow(at: touchPoint) {

          self. heightForCell = // height you want to set 
          // now reload cell again
    }
} 
}

我不喜歡用文字詳細解釋事物,因此我不會給出冗長的答案,而是只包含一個相對較短的代碼(也可作為gist 使用),其中包含解釋基礎知識的注釋。 我並沒有真正關注架構和干凈的代碼,我只是專注於完成任務。 將代碼視為這樣 - 嘗試在您的代碼庫中使其更好。

無論如何,代碼應該非常清晰且一目了然,但在您深入研究之前,我只想為您勾勒出一幅大圖。 在解決方案中,我將高度保留在CGFloat數組(變量cellHeights )中,並通過更改數組中的相應高度來修改給定行的高度。 該數組用作heightForRowAt實現的基礎。

當長按開始時,我啟動一個計時器,通過修改cellHeights數組中的高度並告訴tableView重繪自身,每 0.1 秒更新一次所選行的高度。 這種情況會發生,直到達到該給定行的限制,然后我簡單地取消(無效)計時器。

如果長按在達到限制高度之前結束,我只是明確取消計時器,以便在用戶釋放按下時單元格停止放大。

就是這樣。 我建議你拿EnlargingCellsOnLongPressController gist (或下面的那個,它是相同的代碼),在你自己的設備上嘗試,閱讀代碼和注釋,我相信你應該能夠在你自己的情況下實現它。

import UIKit

class EnlargingCellsOnLongPressController: UITableViewController {
    // this will hold the indexPath of the cell we are currently enlarging
    var enlargingIndexPath: IndexPath?
    // dummy data model
    var modelItems: [String] = []

    // we will need to keep the heights for each particular cell (since any can be resized)
    var cellHeights: [CGFloat] = []

    // some height limit, I will set it for myself to 200
    let limitHeight = CGFloat(200)

    // the enlarging itself will be done by a timer
    weak var timer: Timer?

    override func viewDidLoad() {
        super.viewDidLoad()
        // nothing special here
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        tableView.estimatedRowHeight = 100
        tableView.allowsSelection = false

        // creating some dummy data, 30 items, and for each a cell height that will start at 100
        for index in 0..<30 {
            modelItems.append("Item \(index)")
            // by default we will start with 100
            cellHeights.append(CGFloat(100))
        }

        // please, use swift 4 and the new #selector syntax
        let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPress(longPressGestureRecognizer:)))
        longPressRecognizer.minimumPressDuration = 1
        self.view.addGestureRecognizer(longPressRecognizer)
    }

    // following three methods should be clear
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = modelItems[indexPath.row]
        return cell
    }

    // for height for row we will return a specific height from cellHeights array
    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return cellHeights[indexPath.row]
    }

    @objc func longPress(longPressGestureRecognizer: UILongPressGestureRecognizer) {
        if longPressGestureRecognizer.state == UIGestureRecognizerState.began {
            let touchPoint = longPressGestureRecognizer.location(in: self.tableView)
            if let indexPath = tableView.indexPathForRow(at: touchPoint) {
                //when the press starts on a cell, we will keep the indexPath for the cell
                self.enlargingIndexPath = indexPath
                // and turn on enlarging
                self.startEnlarging()
            }
        } else if longPressGestureRecognizer.state == .ended {
            // when the press is ended, we can stop enlarging
            stopEnlarging()
        }
    }

    func startEnlarging() {
        // interval 0.1 second seems smooth enough (redraw seems to be animated anyway)
        timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { [weak self] (timer) in
            guard let strongSelf = self, let enlargingIndexPath = self?.enlargingIndexPath else { return }

            let oldHeight = strongSelf.cellHeights[enlargingIndexPath.row]
            // since the timer repeats every 0.1 second, this will enlarge the cell 20 points per second till limit
            // in one cycle I will enlarge the cell by two points
            let newHeight = oldHeight + 2
            if newHeight < strongSelf.limitHeight {
                // if the newHeight did not reach limit,
                // update height and redraw tableView
                strongSelf.cellHeights[enlargingIndexPath.row] = newHeight
                strongSelf.tableView.beginUpdates()
                strongSelf.tableView.setNeedsLayout()
                strongSelf.tableView.endUpdates()
            } else {
                // reached maximum size, just cancel the timer
                strongSelf.stopEnlarging()
            }
        })
    }

    func stopEnlarging() {
        // this just cancels the timer
        timer?.invalidate()
    }
}

更新

為了完整起見,我使用 autolayout 和UITableViewAutomaticDimension創建了一個要點,如果您決定使用它而不是heightForRowAt 但原理是一樣的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM