ios - Swift - 滚动 Collection View 时标签移动到单元格的左上角

标签 ios swift scroll uicollectionview cell

每个单元格都有一个带有标签的标题,它应该位于单元格的中央。当 View Controller 第一次出现时,每个标签都正确显示,但是当我向下滚动第一个单元格时,将标签移动到左上角,当我向上滚动时,最后一个单元格也会移动标签。如何将每个标签设置为固定在其初始位置?

class TopicsVC: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UISearchBarDelegate {

override func viewDidLoad() {
self.filteredNames = self.names

    self.collectionView.register(SearchCollectionViewCell.self, forCellWithReuseIdentifier: "SearchCollectionViewCell.identifier")
    self.collectionView.register(TextCollectionViewCell.self, forCellWithReuseIdentifier: "TextCollectionViewCell.identifier")

    if let collectionViewLayout = self.collectionView.collectionViewLayout as? RSKCollectionViewRetractableFirstItemLayout {

        collectionViewLayout.firstItemRetractableAreaInset = UIEdgeInsets(top: 8.0, left: 0.0, bottom: 8.0, right: 0.0)
    }
}


 fileprivate let names = ["F", "N", "S", "M", "R", "T", "A", "M", "T", "F"]

fileprivate let images = ["f.png", "n.png", "s.png", "m.png", "r.png", "t.png", "a.png","m.png","t.png","f.png"]

// MARK: - Layout

internal override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()

    guard self.readyForPresentation == false else {

        return
    }

    self.readyForPresentation = true

    let searchItemIndexPath = IndexPath(item: 0, section: 0)
    self.collectionView.contentOffset = CGPoint(x: 0.0, y: self.collectionView(self.collectionView, layout: self.collectionView.collectionViewLayout, sizeForItemAt: searchItemIndexPath).height)
}

// MARK: - UICollectionViewDataSource

internal func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    switch indexPath.section {

    case 0:
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchCollectionViewCell.identifier", for: indexPath) as! SearchCollectionViewCell

        cell.searchBar.delegate = self
        cell.searchBar.searchBarStyle = .minimal
        cell.searchBar.placeholder = "Search a topic"

        return cell

    case 1:
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TextCollectionViewCell.identifier", for: indexPath) as! TextCollectionViewCell

        let name = self.filteredNames[indexPath.item]

        cell.colorView.layer.cornerRadius = 10.0
        cell.colorView.layer.masksToBounds = true
        //cell.colorView.backgroundColor = self.colors[name]


        cell.colorView.backgroundColor = UIColor(patternImage: UIImage(named: images[indexPath.row])!)
        cell.colorView.layer.contents = UIImage.init(named:images[indexPath.row])!.cgImage


        cell.label.textColor = UIColor.white
        cell.label.font = UIFont(name:"HelveticaNeue-Bold", size: 24.0)
        cell.label.sizeToFit()
        cell.label.numberOfLines = 2
        cell.label.textAlignment = .center
        cell.label.text = name

        return cell

    default:
        assert(false)
    }
}

internal func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    switch section {

    case 0:
        return 1

    case 1:
        return self.filteredNames.count

    default:
        assert(false)
    }
}

internal func numberOfSections(in collectionView: UICollectionView) -> Int {

    return 2
}

// MARK: - UICollectionViewDelegateFlowLayout

internal func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

    switch section {

    case 0:
        return UIEdgeInsets.zero

    case 1:
        return UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0)

    default:
        assert(false)
    }
}

internal func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {

    return 10.0
}

internal func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {

    return 10.0
}

internal func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    switch indexPath.section {

    case 0:
        let itemWidth = collectionView.frame.width
        let itemHeight: CGFloat = 150.0

        return CGSize(width: itemWidth, height: itemHeight)

    case 1:
        let numberOfItemsInLine: CGFloat = 2

        let inset = self.collectionView(collectionView, layout: collectionViewLayout, insetForSectionAt: indexPath.section)
        let minimumInteritemSpacing = self.collectionView(collectionView, layout: collectionViewLayout, minimumInteritemSpacingForSectionAt: indexPath.section)

        let itemWidth = (collectionView.frame.width - inset.left - inset.right - minimumInteritemSpacing * (numberOfItemsInLine - 1)) / numberOfItemsInLine
        let itemHeight = itemWidth


        return CGSize(width: itemWidth, height: itemHeight)

    default:
        assert(false)
    }
}

// MARK: - UIScrollViewDelegate

internal func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {

    guard scrollView === self.collectionView else {

        return
    }

    let indexPath = IndexPath(item: 0, section: 0)
    guard let cell = self.collectionView.cellForItem(at: indexPath) as? SearchCollectionViewCell else {

        return
    }

    guard cell.searchBar.isFirstResponder else {

        return
    }

    cell.searchBar.resignFirstResponder()
}

// MARK: - UISearchBarDelegate

internal func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    let oldFilteredNames = self.filteredNames!

    if searchText.isEmpty {

        self.filteredNames = self.names
    }
    else {

        self.filteredNames = self.names.filter({ (name) -> Bool in

            return name.hasPrefix(searchText)
        })
    }

    self.collectionView.performBatchUpdates({

        for (oldIndex, oldName) in oldFilteredNames.enumerated() {

            if self.filteredNames.contains(oldName) == false {

                let indexPath = IndexPath(item: oldIndex, section: 1)
                self.collectionView.deleteItems(at: [indexPath])
            }
        }

        for (index, name) in self.filteredNames.enumerated() {

            if oldFilteredNames.contains(name) == false {

                let indexPath = IndexPath(item: index, section: 1)
                self.collectionView.insertItems(at: [indexPath])
            }
        }

    }, completion: nil)
}

最佳答案

可能是 collectionView(_:, cellForItemAt:) 实现中的代码:cell.label.sizeToFit() 导致了问题。我建议删除该行。

推理:如果您已经在 Interface Builder 中将标签设置为单元格中的文本居中,则无需在此处更新标签大小。调整大小以适应可能会导致标签缩小,可能会导致您所描述的似乎向左上角移动的行为。

(更糟糕的是,上面代码中对 sizeToFit() 的调用发生在您实际为单元格设置新文本之前,因此其结果将基于单元格中的文本之前它被重复使用。)

关于ios - Swift - 滚动 Collection View 时标签移动到单元格的左上角,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51717102/

相关文章:

ios - iPhoneX : AVCaptureVideoPreviewLayer not occupying the entire screen?

ios - 如何从 cocoapods 版本列表中移动特定的 cocoapods 版本?

ios - 关闭并弹出一个 View Controller

javascript - 使用 jQuery 应用溢出值后 scrollTop() 不工作?

android - 如何停止 Android 中 WebView 的内部滚动?

ios - PredictHQ API 上的 "Bad Request"响应 [ "error": invalid_client] "authentication" request

ios - UIPickerView picker.reloadAllComponents() 在 swift 4 中不起作用

javascript - 从 JSContext 中的 JS Promise/async 函数获取值

ios - Swift - (字符串)无法读取数据

c# - 如何使 PictureBox 可滚动