UITegmentControl与UITableView - UITableViewCell布局在更改段时保持不变

时间:2017-10-05 11:35:49

标签: ios swift uitableview uisegmentedcontrol

在问题标题中提到的场景中,在更改细分时,理想情况下UITableView应该重新加载,因此UITableViewCell也应该重新加载。问题是,所有内容都像标签文本一样更新。但是如果我在一个片段中扩展了单元格的子视图,则在片段更改后它仍然会保持扩展 段索引更改功能:

@IBAction func segmentOnChange(sender: UISegmentControl)
{
    // Few lines
    // self.tableMenu.reloadData()
}

屏幕截图1:

enter image description here

屏幕截图2:

enter image description here

理想情况下,在屏幕截图2中,购物车视图应该已折叠。

更新:

显示/隐藏视图:

func showHideCartView(sender: UIButton)
    {
        let cell = self.tableMenu.cellForRow(at: IndexPath(row: 0, section: Int(sender.accessibilityHint!)!)) as! RestaurantMenuItemCell
        if sender.tag == 1
        {
            // Show cart view
            cell.buttonArrow.tag = 2
            cell.viewAddToCart.isHidden = false
            cell.constraint_Height_viewAddToCart.constant = 50
            cell.buttonArrow.setImage(UIImage(named: "arrowUp.png"), for: .normal)
        }
        else
        {
            // Show cart view
            cell.buttonArrow.tag = 1
            cell.viewAddToCart.isHidden = true
            cell.constraint_Height_viewAddToCart.constant = 0
            cell.buttonArrow.setImage(UIImage(named: "arrowDown.png"), for: .normal)
        }

        self.tableMenu.reloadData()
    }  

cellForRowAtIndexPath:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "RestaurantMenuItemCell", for: indexPath) as! RestaurantMenuItemCell
        cell.selectionStyle = .none
        let menuItem = self.menuItems[indexPath.section]
        cell.imageViewMenuItem.image = UIImage(named: "recommend0@2x.png")
        cell.labelName.text = menuItem.name
        cell.labelDescription.text = menuItem.description
        cell.labelPrice.text = String(format: "$%i", menuItem.price!)
        cell.buttonArrow.accessibilityHint = String(format: "%i", indexPath.section)
        cell.buttonArrow.addTarget(self, action: #selector(self.showHideCartView(sender:)), for: .touchUpInside)

        return cell
    }

3 个答案:

答案 0 :(得分:1)

由于您依赖发件人按钮的标签来确定单元格是应该以展开状态还是折叠状态显示,因此您需要确保当细分更改时,所有单元格buttonArrow的标记也会发生变化到1。

除非发生这种情况,否则将重复使用单元格,并且由于buttonArrow的标记设置为2,因此它将显示为已展开。

答案 1 :(得分:1)

您正在重复使用单元格,请参阅let cell = tableView.dequeueReusableCell(withIdentifier: "RestaurantMenuItemCell", for: indexPath) as! RestaurantMenuItemCell 实施的第一行:

indexPath

这意味着tableView不会创建新单元格,也不会重绘它,除非给定isHidden需要。但是,在代码中,您通过在单元的子视图上设置一些高度约束和tableView标志来展开单元格。现在,一旦您在新段重新加载表,cellForRowAt将使用已经渲染的单元格使重新加载尽可能高效。但是,这意味着,虽然您将更改单元格中的数据,但除非您明确地将其折叠,否则它将保持展开状态(因为之前您已将约束设置为展开高度)。

更改细分时,需要重置展开状态。现在让我们详细说明,因为我相信你当前的解决方案中有一个隐藏的错误:

首先,因为正如我所说的那样你将单元格出列,如果表格中有很多项目并且你正在滚动它们,那么扩展的单元格很有可能在以后的某个地方被重用在表格视图中。所以似乎也有一些随机项目也在扩展。

因此,我建议您提供一些能够记住哪些单元格应该被展开的模型,然后使用此模型中的信息更新每个单元格的状态,然后再将其返回cellForRowAt。该模型可以是例如整数值的简单数组,其将表示扩展的单元格的索引 - 例如,如果数组中存在索引3,则意味着应该扩展第3行的单元格。然后,当您在indexPath中使用行= 3将tableView.reloadData()的单元格出列时,您应该在返回之前为该单元格设置约束。这样你就可以删除我提到的bug。此外,当您更改段时,您可以从阵列中删除所有索引,以表示不再应该扩展单元格(在调用'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', 'localhost'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', //'strict' => true, #####I COMMENTED THIS#### 'modes' => [ //'ONLY_FULL_GROUP_BY', #####AND THIS#### 'STRICT_TRANS_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'ERROR_FOR_DIVISION_BY_ZERO', 'NO_AUTO_CREATE_USER', 'NO_ENGINE_SUBSTITUTION', ], 'engine' => null, ], 之前执行此操作)。

答案 2 :(得分:0)

这里发生了什么,当你点击任何一行然后它会在showHideCartView方法中基于make true first条件进行扩展,之后当你改变保持前一行高度的段索引时,因为你正在重复使用单元格当您更改段索引时,必须设置每行的正常高度。

为此,请将indexPath的对象视为

var selectedIndexPath: NSIndexPath?

然后在selectedIndexPath方法

中设置showHideCartView
func showHideCartView(sender: UIButton) {
  selectedIndexPath = NSIndexPath(row: 0, section: Int(sender.accessibilityHint!)!)) // you can change row and section as per your requirement.

 //// Your other code
}

然后在更改段索引时应用以下逻辑。

@IBAction func segmentOnChange(sender: UISegmentControl)
{
        if indexPath = selectedIndexPath { // check selectedIndexPath is not nil
          let cell = self.tableMenu.cellForRow(at: indexPath) as! RestaurantMenuItemCell
          cell.buttonArrow.tag = 1
          cell.viewAddToCart.isHidden = true
          cell.constraint_Height_viewAddToCart.constant = 0
          cell.buttonArrow.setImage(UIImage(named: "arrowDown.png"), for: .normal)
        }

    selectedIndexPath = nil // assign nil to selectedIndexPath
    // Few lines

  self.tableMenu.reloadData()  // Reload your tableview

}