簡體   English   中英

在Swift中點擊展開單元格

[英]Expand cell when tapped in Swift

我一直在嘗試在我的應用程序中實現一項功能,以便當用戶在我的表格視圖中點擊一個單元格時,該單元格向下擴展以顯示注釋。 我在Objective-C中找到了很多這樣的例子,但是我還沒有找到Swift的例子。

這個示例似乎很完美: 手風琴表單元格-如何動態擴展/收縮uitableviewcell?

我試圖將其翻譯為Swift:

var selectedRowIndex = NSIndexPath()
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    selectedRowIndex = indexPath
    tableView.beginUpdates()
    tableView.endUpdates()
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if selectedRowIndex == selectedRowIndex.row && indexPath.row == selectedRowIndex.row {
        return 100
    }
    return 70
}

但是,這似乎會使應用程序崩潰。

有任何想法嗎?

編輯:

這是我的cellForRowAtIndexPath代碼:

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell:CustomTransactionTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as CustomTransactionTableViewCell

    cell.selectionStyle = UITableViewCellSelectionStyle.None

    if tableView == self.searchDisplayController?.searchResultsTableView {
        cell.paymentNameLabel.text = (searchResults.objectAtIndex(indexPath.row)) as? String
        //println(searchResults.objectAtIndex(indexPath.row))
        var indexValue = names.indexOfObject(searchResults.objectAtIndex(indexPath.row))
        cell.costLabel.text = (values.objectAtIndex(indexValue)) as? String
        cell.dateLabel.text = (dates.objectAtIndex(indexValue)) as? String

        if images.objectAtIndex(indexValue) as NSObject == 0 {
            cell.paymentArrowImage.hidden = false
            cell.creditArrowImage.hidden = true
        } else if images.objectAtIndex(indexValue) as NSObject == 1 {
            cell.creditArrowImage.hidden = false
            cell.paymentArrowImage.hidden = true
        }
    } else {
        cell.paymentNameLabel.text = (names.objectAtIndex(indexPath.row)) as? String
        cell.costLabel.text = (values.objectAtIndex(indexPath.row)) as? String
        cell.dateLabel.text = (dates.objectAtIndex(indexPath.row)) as? String

        if images.objectAtIndex(indexPath.row) as NSObject == 0 {
            cell.paymentArrowImage.hidden = false
            cell.creditArrowImage.hidden = true
        } else if images.objectAtIndex(indexPath.row) as NSObject == 1 {
            cell.creditArrowImage.hidden = false
            cell.paymentArrowImage.hidden = true
        }
    }
    return cell
}

這是插座設置:

在此處輸入圖片說明

我花了很多時間才能使它生效。 以下是我的解決方法。

PS:@rdelmar代碼的問題在於他假設您的表中只有一個section ,因此他只比較indexPath.row 如果您有多個部分(或者如果您想稍后再考慮擴展代碼),則應比較整個索引,如下所示:

1)您需要一個變量來告訴您選擇了哪一行。 我看到您已經這樣做了,但是您需要將變量恢復為一致的“未選中”狀態(用戶關閉所有單元格時)。 我相信最好的方法是通過可選的:

var selectedIndexPath: NSIndexPath? = nil

2)您需要確定用戶何時選擇一個單元格。 didSelectRowAtIndexPath是顯而易見的選擇。 您需要考慮以下三種可能的結果:

  1. 用戶點擊一個單元格,另一個單元格被展開
  2. 用戶正在點擊一個單元格並且沒有單元格展開
  3. 用戶點擊一個已經擴展的單元格

對於每種情況,我們都會檢查selectedIndexPath是否等於nil(不擴展任何單元格),等於被輕擊的行的indexPath(已擴展同一單元格)或與indexPath不同(擴展另一個單元格)。 我們相應地調整selectedIndexPath。 此變量將用於檢查每行的正確rowHeight。 您在注釋中提到didSelectRowAtIndexPath “似乎沒有被調用”。 您是否正在使用println()並檢查控制台以查看是否已調用它? 我在下面的代碼中包含了一個。

PS:使用tableView.rowHeight不能正常工作,因為顯然在更新tableView中的所有行之前,Swift僅檢查一次rowHeight。

最后但並非最不重要的一點是,我使用reloadRowsAtIndexPath僅重新加載所需的行。 而且,因為我知道它會重繪表格,在必要時重新布局,甚至為更改添加動畫效果。 請注意, [indexPath]位於方括號之間,因為此方法需要一個NSIndexPath數組:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        println("didSelectRowAtIndexPath was called")
        var cell = tableView.cellForRowAtIndexPath(indexPath) as! MyCustomTableViewCell
        switch selectedIndexPath {
        case nil:
            selectedIndexPath = indexPath
        default:
            if selectedIndexPath! == indexPath {
                selectedIndexPath = nil
            } else {
                selectedIndexPath = indexPath
            }
        }
        tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}

3)第三步也是最后一步,Swift需要知道何時將每個值傳遞到像元高度。 我們在這里使用if / else進行類似的檢查。 我知道您可以使代碼更短一些,但是我正在鍵入所有內容,以便其他人也可以輕松理解它:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        let smallHeight: CGFloat = 70.0
        let expandedHeight: CGFloat = 100.0
        let ip = indexPath
        if selectedIndexPath != nil {
            if ip == selectedIndexPath! {
                return expandedHeight
            } else {
                return smallHeight
            }
        } else {
            return smallHeight
        }
    }

現在,如果上面的代碼不能解決問題,則可能是您的代碼問題的一些注釋:

var cell:CustomTransactionTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as CustomTransactionTableViewCell

我不知道這是否是問題,但self不必說,因為您可能會將這段代碼放在(Custom)TableViewController中。 另外,如果您正確地強制從出隊中強制投射單元,則可以不用指定變量類型,而可以信任Swift的推論。 那個力量鑄就了as! 在下面的代碼中:

var cell = tableView.dequeueReusableCellWithIdentifier("CellIdentifier" forIndexPath: indexPath) as! CustomTransactionTableViewCell

但是,您絕對需要設置該標識符。 轉到情節提要,選擇具有所需單元格的tableView,作為所需TableViewCell的子類(在您的情況下可能是CustomTransactionTableViewCell )。 現在,在TableView中選擇單元格(檢查是否選擇了正確的元素。最好通過“編輯器”>“顯示文檔輪廓”打開文檔輪廓)。 選中單元格后,轉到右側的“屬性”檢查器,然后鍵入“ Identifier名稱。

您也可以嘗試注釋掉cell.selectionStyle = UITableViewCellSelectionStyle.None來檢查是否以任何方式阻止了選擇(通過這種方式,當單元格被選中時,單元格將改變顏色)。

祝你好運,隊友。

if語句中的第一個比較永遠不會為真,因為您正在將indexPath與整數進行比較。 您還應該使用表中不能包含的行值來初始化selectedRowIndex變量,例如-1,因此在表首次加載時不會展開任何內容。

var selectedRowIndex: NSIndexPath = NSIndexPath(forRow: -1, inSection: 0)

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if indexPath.row == selectedRowIndex.row {
        return 100
    }
    return 70
}

Swift 4.2 var selectedRowIndex: NSIndexPath = NSIndexPath(row: -1, section: 0)

一種不同的方法是在導航堆棧中推送新的視圖控制器,並將過渡用於擴展效果。 好處將是SoC(關注點分離)。 兩個模式的示例Swift 2.0項目。

我建議用modyfing高度布局約束來解決這個問題

class ExpandableCell: UITableViewCell {

@IBOutlet weak var img: UIImageView!


@IBOutlet weak var imgHeightConstraint: NSLayoutConstraint!


var isExpanded:Bool = false
    {
    didSet
    {
        if !isExpanded {
            self.imgHeightConstraint.constant = 0.0

        } else {
            self.imgHeightConstraint.constant = 128.0
        }
    }
}

}

然后,在ViewController中:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
    super.viewDidLoad()
    self.tableView.delegate = self
    self.tableView.dataSource = self
    self.tableView.estimatedRowHeight = 2.0
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.tableFooterView = UIView()
}


// TableView DataSource methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 3
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell:ExpandableCell = tableView.dequeueReusableCell(withIdentifier: "ExpandableCell") as! ExpandableCell
    cell.img.image = UIImage(named: indexPath.row.description)
    cell.isExpanded = false
    return cell
}

// TableView Delegate methods
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    guard let cell = tableView.cellForRow(at: indexPath) as? ExpandableCell
        else { return }

        UIView.animate(withDuration: 0.3, animations: {
            tableView.beginUpdates()
            cell.isExpanded = !cell.isExpanded
            tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.top, animated: true)
            tableView.endUpdates()

        })

    }




func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    guard let cell = tableView.cellForRow(at: indexPath) as? ExpandableCell
        else { return }
    UIView.animate(withDuration: 0.3, animations: {
        tableView.beginUpdates()
        cell.isExpanded = false
        tableView.endUpdates()
    })
}
}

完整的教程在這里

didSelectRowAtIndexPath獲取索引路徑后,只需使用以下方法reloadCellsAtIndexpath重新加載單元格,並在heightForRowAtIndexPathMethod檢查以下條件

if selectedIndexPath != nil && selectedIndexPath == indexPath {    
       return yourExpandedCellHieght
}

暫無
暫無

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

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