使用 CGAffineTransform 缩放 tableView 单元格以覆盖整个屏幕

Posted

技术标签:

【中文标题】使用 CGAffineTransform 缩放 tableView 单元格以覆盖整个屏幕【英文标题】:Scale tableView cell with CGAffineTransform to cover entire screen 【发布时间】:2020-05-17 06:05:21 【问题描述】:

我有一个 tableView,当用户点击该单元格时,我希望该单元格展开并用该颜色填充整个屏幕。目前,它确实可以缩放以填满整个屏幕,但它上面的单元格也会显示。颜色来自 API,当用户点击“生成”按钮时,每个单元格都会改变颜色。由于 API 的 JSON 文件的结构,我一次只需要 5 种颜色在屏幕上。

我不知道为什么它上面的单元格没有向上移动,或者我如何将点击的单元格移动到屏幕顶部。我已经尝试偏移点击单元格的坐标并将其帧大小更改为 tableView tappedCell.bounds.size = CGSize(width: UIScreen.main.bounds.width, height: self.paletteTableView.bounds.height) 的高度,但是当我从顶部单击第一个或第二个单元格时,屏幕不会一直填充到底部。

我也尝试过从 UIView(这里称为 colorDetailsView)制作动画,但无法成功地让它从被点击的每个单元格的中心制作动画,只能从屏幕中心制作。

动画发生在这里:

@objc func userTap(sender: UITapGestureRecognizer) 
        if sender.state == UIGestureRecognizer.State.ended 
            let tapLocation = sender.location(in: self.paletteTableView)
            if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation) 
                if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) 

                    UIView.animate(withDuration: 0.5, animations: 

                        switch self.currentAnimation 
                        case 0:
                            tappedCell.transform = CGAffineTransform(scaleX: 1, y: 50)
                            //...
                        case 1:
                            tappedCell.transform = .identity
                        default: break
                        
                     )

                    currentAnimation += 1
                    if currentAnimation > 1 
                        currentAnimation = 0
        

完整代码:

class PaletteController: UIViewController, UITableViewDataSource, UITableViewDelegate 

    let tableView = UITableView()
    var colorPalette = [Color]()
    var currentAnimation = 0

    let colorDetailsView: UIView = 
        let view = UIView()
        return view
    ()

    override func viewDidLoad() 
        super.viewDidLoad()
        tableView.dataSource = self
        tableView.delegate = self
        tableView.isScrollEnabled = false
        \\...
        view.addSubview(colorDetailsView)
    

    //Color cell expands to fill the screen of that color when user taps on the cell
    @objc func userTap(sender: UITapGestureRecognizer) 
        if sender.state == UIGestureRecognizer.State.ended 
            let tapLocation = sender.location(in: self.tableView)

            if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation) 
                if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) 
                    UIView.animate(withDuration: 0.5, animations: 

                        //When user taps on a cell, it is scaled to fill the screen with that color
                        switch self.currentAnimation 
                        case 0:
                            tappedCell.transform = CGAffineTransform(scaleX: 1, y: 50)

                            for i in 0..<self.colorPalette.count 
                                    if tapIndexPath.row == i 
                                        self.colorDetailsView.backgroundColor = UIColor(hexString: self.colorPalette[i])
                                    
                                
                        case 1:
                            tappedCell.transform = .identity
                        default: break
                        
                     )

                    currentAnimation += 1
                    if currentAnimation > 1 
                        currentAnimation = 0
                    
                
            
        
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 5
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier:"ColorCell", for: indexPath)

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(userTap(sender:)))
        cell.addGestureRecognizer(tapGesture)
        cell.isUserInteractionEnabled = true

        //Assigns a new color to each row. Colors are converted from HEX to RGB
        for i in 0..<colorPalette.count 
            if tapIndexPath.row == i 
                cell.backgroundColor = UIColor(hexString: colorPalette[i])
            
        
        return cell
    

当我将tableView.isScrollEnabled 设置为true 时,我知道单元格正在缩放,如下所示。每个单元格最终应该填满整个屏幕,并且不会被任何其他单元格覆盖,例如最上面的单元格。理想情况下,我希望 tableView 不滚动,但我不确定如果禁用滚动,顶部单元格是否会“向上移动”。

感谢任何帮助!

【问题讨论】:

【参考方案1】:

单元格毕竟是表格视图的所有子视图。您需要将点击的单元格放在子视图列表的前面。

我建议添加

tableView.bringSubviewToFront(tappedCell)

就在这条线之后

if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) .

看看这是否有效!

【讨论】:

非常感谢您的建议!真希望早点看到你的回答。实际上,我只是在摆弄了一段时间后才发现 .bringSubviewToFront 并解决了我的问题 发生在我们所有人身上:)

以上是关于使用 CGAffineTransform 缩放 tableView 单元格以覆盖整个屏幕的主要内容,如果未能解决你的问题,请参考以下文章

CGAffineTransform 缩放和平移 - 动画前跳转

CGAffineTransform

CGAffineTransform 操作顺序不一致

如何使用 CGAffineTransform Scale 从右到左添加动画和放大动画

CGAffineTransform:如何计算乘法 CGAffineTransform?

CGAffineTransform-仿射矩阵的变换